feat: improve server management and refund display
Server Management: - Fix /server command API auth (query param instead of header) - Show server specs (vCPU/RAM/Bandwidth) in /server list - Prevent AI from refusing server deletion based on expiration date - Add explicit instructions in tool description and system prompt Refund Display: - Show before/after balance in server deletion refund message - Format: 환불 전 잔액 → 환불 금액 → 환불 후 잔액 Other Changes: - Add stopped status migration for server orders - Clean up callback handler (remove deprecated code) - Update constants and pattern utilities Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
321
docs/CONSTANTS_MIGRATION.md
Normal file
321
docs/CONSTANTS_MIGRATION.md
Normal file
@@ -0,0 +1,321 @@
|
||||
# Constants Migration Guide
|
||||
|
||||
**Status**: Constants file created ✅ | Usage migration pending 🚧
|
||||
|
||||
This document tracks the migration of magic strings to the centralized `/src/constants/index.ts` file.
|
||||
|
||||
## Overview
|
||||
|
||||
Magic strings have been extracted into constants for:
|
||||
- Better maintainability
|
||||
- Type safety
|
||||
- Consistency
|
||||
- Easier refactoring
|
||||
|
||||
**Note**: This is a gradual migration. The constants file is ready, but actual usage changes should be done carefully to avoid breaking changes.
|
||||
|
||||
## Usage Locations
|
||||
|
||||
### SESSION_KEYS.DELETE_CONFIRM (`delete_confirm:`)
|
||||
|
||||
**Files using this string:**
|
||||
- `/src/routes/api/chat.ts:213` - Delete confirmation session creation
|
||||
- `/src/routes/api/chat.ts:248` - Delete confirmation session retrieval
|
||||
- `/src/routes/handlers/message-handler.ts:60` - Delete confirmation check
|
||||
- `/src/tools/server-tool.ts:1005` - Server deletion confirmation
|
||||
|
||||
**Migration example:**
|
||||
```typescript
|
||||
// Before
|
||||
const deleteSessionKey = `delete_confirm:${telegramUserId}`;
|
||||
|
||||
// After
|
||||
import { SESSION_KEYS, sessionKey } from './constants';
|
||||
const deleteSessionKey = sessionKey(SESSION_KEYS.DELETE_CONFIRM, telegramUserId);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### MESSAGE_MARKERS.DIRECT (`__DIRECT__`)
|
||||
|
||||
**Files using this marker:**
|
||||
- `/src/services/conversation-service.ts:48-51` - Direct marker removal logic
|
||||
- `/src/openai-service.ts:327-352` - Early return check and processing
|
||||
- `/src/routes/api/chat.ts:127-130` - Web chat direct marker handling
|
||||
- `/src/routes/api/chat.ts:426-429` - Another web chat instance
|
||||
- `/src/tools/server-tool.ts:343-840` - Server tool responses (multiple locations)
|
||||
- `/src/tools/domain-tool.ts` - Domain tool responses
|
||||
- `/src/tools/troubleshoot-tool.ts:68` - Troubleshoot tool response
|
||||
- `/src/summary-service.ts:408` - System prompt instruction
|
||||
|
||||
**Migration example:**
|
||||
```typescript
|
||||
// Before
|
||||
if (responseText.includes('__DIRECT__')) {
|
||||
const directIndex = responseText.indexOf('__DIRECT__');
|
||||
responseText = responseText.slice(directIndex + '__DIRECT__'.length).trim();
|
||||
}
|
||||
|
||||
// After
|
||||
import { MESSAGE_MARKERS } from './constants';
|
||||
if (responseText.includes(MESSAGE_MARKERS.DIRECT)) {
|
||||
const directIndex = responseText.indexOf(MESSAGE_MARKERS.DIRECT);
|
||||
responseText = responseText.slice(directIndex + MESSAGE_MARKERS.DIRECT.length).trim();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### MESSAGE_MARKERS.KEYBOARD (`__KEYBOARD__` and `__END__`)
|
||||
|
||||
**Files using these markers:**
|
||||
- `/src/services/conversation-service.ts:69-80` - Keyboard parsing logic
|
||||
- `/src/openai-service.ts:327-328` - Early return check
|
||||
- `/src/tools/domain-tool.ts:799` - Keyboard data generation
|
||||
- `/src/routes/api/chat.ts:127-130` - Web chat (mentioned in grep)
|
||||
|
||||
**Migration example:**
|
||||
```typescript
|
||||
// Before
|
||||
const keyboardMatch = responseText.match(/__KEYBOARD__(.+?)__END__\n?/s);
|
||||
responseText = responseText.replace(/__KEYBOARD__.+?__END__\n?/s, '');
|
||||
|
||||
// After
|
||||
import { MESSAGE_MARKERS } from './constants';
|
||||
const pattern = new RegExp(`${MESSAGE_MARKERS.KEYBOARD}(.+?)${MESSAGE_MARKERS.KEYBOARD_END}\\n?`, 's');
|
||||
const keyboardMatch = responseText.match(pattern);
|
||||
responseText = responseText.replace(pattern, '');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### MESSAGE_MARKERS.PASSTHROUGH (`__PASSTHROUGH__`)
|
||||
|
||||
**Files using this marker:**
|
||||
- `/src/server-agent.ts:660` - Session end, return to normal conversation
|
||||
- `/src/server-agent.ts:716` - Another session transition
|
||||
- `/src/openai-service.ts:233` - Function call result check
|
||||
- `/src/openai-service.ts:257` - Another function call result check
|
||||
- `/src/troubleshoot-agent.ts:421` - Agent transition
|
||||
|
||||
**Migration example:**
|
||||
```typescript
|
||||
// Before
|
||||
if (result !== '__PASSTHROUGH__') {
|
||||
return result;
|
||||
}
|
||||
|
||||
// After
|
||||
import { MESSAGE_MARKERS } from './constants';
|
||||
if (result !== MESSAGE_MARKERS.PASSTHROUGH) {
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### SESSION_KEYS.SERVER_SESSION (`server_session:`)
|
||||
|
||||
**Files using this string:**
|
||||
- `/src/server-agent.ts` - Server consultation session management
|
||||
|
||||
**Migration example:**
|
||||
```typescript
|
||||
// Before
|
||||
const sessionKey = `server_session:${userId}`;
|
||||
|
||||
// After
|
||||
import { SESSION_KEYS, sessionKey } from './constants';
|
||||
const key = sessionKey(SESSION_KEYS.SERVER_SESSION, userId);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### TRANSACTION_STATUS values
|
||||
|
||||
**Files using these strings:**
|
||||
- `/src/routes/api/deposit.ts` - Deposit API endpoints
|
||||
- `/src/tools/deposit-tool.ts` - Deposit tool actions
|
||||
- `/src/deposit-agent.ts` - Deposit agent logic
|
||||
- `/src/services/deposit-matcher.ts` - Auto-matching service
|
||||
- `/src/utils/reconciliation.ts` - Reconciliation job
|
||||
- `/tests/deposit-agent.test.ts` - Test cases
|
||||
|
||||
**Common patterns:**
|
||||
- `status = 'pending'`
|
||||
- `status = 'confirmed'`
|
||||
- `status = 'cancelled'`
|
||||
- `status = 'rejected'`
|
||||
|
||||
**Migration example:**
|
||||
```typescript
|
||||
// Before
|
||||
const result = await env.DB.prepare(
|
||||
'SELECT * FROM deposit_transactions WHERE status = ?'
|
||||
).bind('pending').all();
|
||||
|
||||
// After
|
||||
import { TRANSACTION_STATUS } from './constants';
|
||||
const result = await env.DB.prepare(
|
||||
'SELECT * FROM deposit_transactions WHERE status = ?'
|
||||
).bind(TRANSACTION_STATUS.PENDING).all();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### SERVER_ORDER_STATUS values
|
||||
|
||||
**Files using these strings:**
|
||||
- `/src/tools/server-tool.ts` - Server management tool
|
||||
- `/src/server-provision.ts` - Server provisioning logic
|
||||
|
||||
**Common patterns:**
|
||||
- `status = 'pending'`
|
||||
- `status = 'provisioning'`
|
||||
- `status = 'active'`
|
||||
- `status = 'failed'`
|
||||
- `status = 'terminated'`
|
||||
|
||||
**Migration example:**
|
||||
```typescript
|
||||
// Before
|
||||
if (order.status === 'active') {
|
||||
// ...
|
||||
}
|
||||
|
||||
// After
|
||||
import { SERVER_ORDER_STATUS } from './constants';
|
||||
if (order.status === SERVER_ORDER_STATUS.ACTIVE) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CALLBACK_PREFIXES values
|
||||
|
||||
**Files using these strings:**
|
||||
- `/src/routes/handlers/callback-query-handler.ts` - Callback query routing
|
||||
- `/src/tools/domain-tool.ts` - Domain registration buttons
|
||||
- `/src/tools/server-tool.ts` - Server order buttons
|
||||
|
||||
**Common patterns:**
|
||||
- `confirm_domain_register:example.com:15000`
|
||||
- `cancel_domain_register:example.com`
|
||||
- `confirm_server_order:order_123`
|
||||
|
||||
**Migration example:**
|
||||
```typescript
|
||||
// Before
|
||||
if (data.startsWith('confirm_domain_register:')) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// After
|
||||
import { CALLBACK_PREFIXES } from './constants';
|
||||
if (data.startsWith(`${CALLBACK_PREFIXES.DOMAIN_REGISTER_CONFIRM}:`)) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Phase 1: Foundation (✅ Complete)
|
||||
- [x] Create `/src/constants/index.ts`
|
||||
- [x] Define all constants with proper types
|
||||
- [x] Add helper functions (`sessionKey`, `parseSessionKey`)
|
||||
- [x] TypeScript compilation check passes
|
||||
|
||||
### Phase 2: High-Priority Migration (🚧 Pending)
|
||||
**Target**: Critical paths with high maintenance burden
|
||||
|
||||
1. **Session keys** (low risk, high benefit)
|
||||
- `SESSION_KEYS.DELETE_CONFIRM`
|
||||
- `SESSION_KEYS.SERVER_ORDER_CONFIRM`
|
||||
- `SESSION_KEYS.SERVER_SESSION`
|
||||
|
||||
2. **Transaction status checks** (medium risk, high benefit)
|
||||
- Database queries with status filters
|
||||
- Status transitions in business logic
|
||||
|
||||
### Phase 3: Message Markers (🚧 Pending)
|
||||
**Target**: AI response processing
|
||||
|
||||
1. **Direct marker processing**
|
||||
- Standardize removal logic
|
||||
- Create shared utility function
|
||||
|
||||
2. **Keyboard marker processing**
|
||||
- Centralize regex patterns
|
||||
- Improve error handling
|
||||
|
||||
3. **Passthrough checks**
|
||||
- Simple find-and-replace
|
||||
|
||||
### Phase 4: Complete Migration (📅 Future)
|
||||
**Target**: All remaining magic strings
|
||||
|
||||
- Action constants (SERVER_ACTION, DOMAIN_ACTION, DEPOSIT_ACTION)
|
||||
- Callback prefixes
|
||||
- Any remaining hardcoded strings
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
Before merging any migration:
|
||||
|
||||
- [ ] TypeScript compilation passes (`npx tsc --noEmit`)
|
||||
- [ ] All tests pass (`npm test`)
|
||||
- [ ] Manual testing of affected features
|
||||
- [ ] No breaking changes to API contracts
|
||||
- [ ] Documentation updated if needed
|
||||
|
||||
---
|
||||
|
||||
## Benefits of Migration
|
||||
|
||||
1. **Type Safety**: TypeScript can catch typos at compile time
|
||||
2. **Consistency**: All code uses the same string values
|
||||
3. **Refactoring**: Change once, update everywhere
|
||||
4. **Documentation**: Constants serve as inline documentation
|
||||
5. **IDE Support**: Autocomplete and go-to-definition
|
||||
|
||||
---
|
||||
|
||||
## Example: Complete Before/After
|
||||
|
||||
### Before
|
||||
```typescript
|
||||
// Multiple files, inconsistent usage
|
||||
const key1 = `delete_confirm:${userId}`;
|
||||
const key2 = 'delete_confirm:' + userId;
|
||||
if (status === 'pending') { }
|
||||
if (result === '__PASSTHROUGH__') { }
|
||||
```
|
||||
|
||||
### After
|
||||
```typescript
|
||||
import { SESSION_KEYS, TRANSACTION_STATUS, MESSAGE_MARKERS, sessionKey } from './constants';
|
||||
|
||||
const key1 = sessionKey(SESSION_KEYS.DELETE_CONFIRM, userId);
|
||||
const key2 = sessionKey(SESSION_KEYS.DELETE_CONFIRM, userId); // Consistent!
|
||||
if (status === TRANSACTION_STATUS.PENDING) { }
|
||||
if (result === MESSAGE_MARKERS.PASSTHROUGH) { }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- **Gradual migration**: Don't rush. Each change should be tested thoroughly.
|
||||
- **Backward compatibility**: Ensure old code still works during transition.
|
||||
- **Documentation**: Update CLAUDE.md and README.md when major migrations complete.
|
||||
- **Communication**: Notify team when changing widely-used constants.
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2026-01-29
|
||||
**Status**: Foundation complete, awaiting gradual migration
|
||||
Reference in New Issue
Block a user