fix: allow session cancellation in all states
Previously cancellation only worked in 'selecting' or 'ordering' states. Now users can cancel server consultation at any stage using keywords: 취소, 다시, 처음, 리셋, 초기화, 다시 시작, 처음부터 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
91
.tasks/task_1769153089612.md
Normal file
91
.tasks/task_1769153089612.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Server Recommendation Output Format Improvement
|
||||
|
||||
## Objective
|
||||
Improve server recommendation display to table format with provider column and region preference handling.
|
||||
|
||||
## Files to Modify
|
||||
|
||||
### 1. /Users/kaffa/telegram-bot-workers/src/tools/server-tool.ts
|
||||
|
||||
**Location:** `recommendServer()` function around lines 279-294
|
||||
|
||||
**Current Format:**
|
||||
```
|
||||
1. vc2-2c-4gb
|
||||
• 2 vCPUs, 4.0GB RAM, 80GB SSD
|
||||
• 리전: 서울, 한국
|
||||
• 42,100원/월
|
||||
```
|
||||
|
||||
**New Format:**
|
||||
```
|
||||
🎯 **게임서버** 추천
|
||||
|
||||
📊 **분석 결과:** 게임서버 기본 요구사항 / 동시 접속자 50명
|
||||
|
||||
| # | 제공자 | 사양 | vCPU | RAM | 스토리지 | 리전 | 가격/월 |
|
||||
|---|--------|------|------|-----|----------|------|--------|
|
||||
| 1 | Vultr | vc2-2c-4gb | 2 | 4GB | 80GB | 서울 | 35,100원 |
|
||||
| 2 | Linode | 4GB Plan | 4 | 4GB | 160GB | 도쿄 | 42,100원 |
|
||||
| 3 | Linode | 4GB Plan | 4 | 4GB | 160GB | 싱가포르 | 42,100원 |
|
||||
|
||||
💡 주문: "사양 #70455 주문"
|
||||
```
|
||||
|
||||
**Code Change (results.forEach part around line 283-290):**
|
||||
```typescript
|
||||
// 표 헤더
|
||||
let response = `🎯 **${args.purpose || "범용"}** 서버 추천\n\n`;
|
||||
response += `📊 **분석 결과:** ${requirements.reason}\n\n`;
|
||||
response += `| # | 제공자 | 사양 | vCPU | RAM | 스토리지 | 리전 | 가격/월 |\n`;
|
||||
response += `|---|--------|------|------|-----|----------|------|--------|\n`;
|
||||
|
||||
results.forEach((spec, idx) => {
|
||||
const ramGB = (spec.memory_mb / 1024).toFixed(0);
|
||||
// 리전에서 국가 부분만 추출 (예: "서울, 한국" → "서울")
|
||||
const shortRegion = spec.region_name.split(',')[0].trim();
|
||||
response += `| ${idx + 1} | ${spec.provider_name} | ${spec.instance_name} | ${spec.vcpu} | ${ramGB}GB | ${spec.storage_gb}GB | ${shortRegion} | ${spec.monthly_price_krw.toLocaleString()}원 |\n`;
|
||||
});
|
||||
|
||||
response += `\n💡 주문하시려면 "사양 #${results[0].id} 주문"이라고 말씀해주세요.`;
|
||||
|
||||
return response;
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- provider_name is already in query results (line 239: `prov.name as provider_name`)
|
||||
- Extract city only from region_name (before comma)
|
||||
- RAM should be whole number (0 decimals)
|
||||
|
||||
### 2. /Users/kaffa/telegram-bot-workers/src/summary-service.ts
|
||||
|
||||
**Location:** System prompt around lines 390-393 (server recommendation section)
|
||||
|
||||
**Current:**
|
||||
```typescript
|
||||
- 서버 추천 요청 시:
|
||||
1. 새로운 추천 요청은 이전 대화와 무관하게 처리
|
||||
2. 용도만 알면 바로 추천 가능. 용도 모르면 한 번만 질문
|
||||
```
|
||||
|
||||
**Change To:**
|
||||
```typescript
|
||||
- 서버 추천 요청 시:
|
||||
1. 새로운 추천 요청은 이전 대화와 무관하게 처리
|
||||
2. 용도와 선호 위치(서울/도쿄/싱가포르)를 모르면 한 번에 질문: "어떤 용도로, 어느 지역 서버를 원하시나요? (서울/도쿄/싱가포르)"
|
||||
3. 위치 선호가 있으면 region 파라미터로 전달 (예: region="Seoul" 또는 region="Tokyo")
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
1. Build: `npm run dev`
|
||||
2. Test message: "게임서버 추천해줘"
|
||||
3. Verify table format renders correctly in Telegram
|
||||
4. Test region preference: "서울 서버로 웹서버 추천"
|
||||
|
||||
## Requirements
|
||||
|
||||
- TypeScript strict mode
|
||||
- No `any` types
|
||||
- Preserve existing functionality
|
||||
- Follow project conventions (kebab-case files, camelCase functions)
|
||||
@@ -479,11 +479,16 @@ export async function processServerConsultation(
|
||||
status: session.status
|
||||
});
|
||||
|
||||
// 취소 키워드 처리 (selecting 또는 ordering 상태에서)
|
||||
if ((session.status === 'selecting' || session.status === 'ordering') &&
|
||||
/취소|다시|처음/.test(userMessage)) {
|
||||
// 취소 키워드 처리 (모든 상태에서 작동)
|
||||
// "취소", "다시", "처음", "리셋", "초기화" 등
|
||||
if (/^(취소|다시|처음|리셋|초기화)/.test(userMessage.trim()) ||
|
||||
/취소할[게래]|다시\s*시작|처음부터/.test(userMessage)) {
|
||||
await deleteServerSession(env.SESSION_KV, session.telegramUserId);
|
||||
logger.info('사용자 요청으로 상담 취소', { userId: session.telegramUserId });
|
||||
logger.info('사용자 요청으로 상담 취소', {
|
||||
userId: session.telegramUserId,
|
||||
previousStatus: session.status,
|
||||
trigger: userMessage.slice(0, 20)
|
||||
});
|
||||
return '상담이 취소되었습니다. 다시 시작하려면 "서버 추천"이라고 말씀해주세요.';
|
||||
}
|
||||
|
||||
|
||||
@@ -4,17 +4,7 @@ import path from 'path';
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'miniflare',
|
||||
environmentOptions: {
|
||||
bindings: {
|
||||
BOT_TOKEN: 'test-bot-token',
|
||||
WEBHOOK_SECRET: 'test-webhook-secret',
|
||||
OPENAI_API_KEY: 'test-openai-key',
|
||||
DEPOSIT_ADMIN_ID: '999999999',
|
||||
},
|
||||
kvNamespaces: ['RATE_LIMIT_KV'],
|
||||
d1Databases: ['DB'],
|
||||
},
|
||||
environment: 'node',
|
||||
setupFiles: ['./tests/setup.ts'],
|
||||
coverage: {
|
||||
provider: 'v8',
|
||||
|
||||
Reference in New Issue
Block a user