Initial implementation of Telegram AI customer support bot
Cloudflare Workers + Hono + D1 + KV + R2 stack with 4 specialized AI agents (onboarding, troubleshoot, asset, billing), OpenAI function calling with 7 tool definitions, human escalation, pending action approval workflow, feedback collection, audit logging, i18n (ko/en), and Workers AI fallback. 43 source files, 45 tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
470
src/types.ts
Normal file
470
src/types.ts
Normal file
@@ -0,0 +1,470 @@
|
||||
// ============================================
|
||||
// Environment
|
||||
// ============================================
|
||||
|
||||
export interface Env {
|
||||
DB: D1Database;
|
||||
AI: Ai;
|
||||
BOT_TOKEN: string;
|
||||
WEBHOOK_SECRET: string;
|
||||
OPENAI_API_KEY?: string;
|
||||
ADMIN_TELEGRAM_IDS?: string;
|
||||
ENVIRONMENT?: string;
|
||||
// Financial
|
||||
DEPOSIT_BANK_NAME?: string;
|
||||
DEPOSIT_BANK_ACCOUNT?: string;
|
||||
DEPOSIT_BANK_HOLDER?: string;
|
||||
// API URLs
|
||||
OPENAI_API_BASE?: string;
|
||||
D2_RENDER_URL?: string;
|
||||
NAMECHEAP_API_URL?: string;
|
||||
WHOIS_API_URL?: string;
|
||||
CLOUD_ORCHESTRATOR_URL?: string;
|
||||
CLOUD_ORCHESTRATOR?: Fetcher;
|
||||
// KV Namespaces
|
||||
RATE_LIMIT_KV: KVNamespace;
|
||||
SESSION_KV: KVNamespace;
|
||||
CACHE_KV: KVNamespace;
|
||||
// R2
|
||||
R2_BUCKET: R2Bucket;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Telegram Types
|
||||
// ============================================
|
||||
|
||||
export interface TelegramUpdate {
|
||||
update_id: number;
|
||||
message?: TelegramMessage;
|
||||
callback_query?: CallbackQuery;
|
||||
}
|
||||
|
||||
export interface CallbackQuery {
|
||||
id: string;
|
||||
from: TelegramUser;
|
||||
message?: TelegramMessage;
|
||||
chat_instance: string;
|
||||
data?: string;
|
||||
}
|
||||
|
||||
export interface TelegramMessage {
|
||||
message_id: number;
|
||||
from: TelegramUser;
|
||||
chat: TelegramChat;
|
||||
date: number;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
export interface TelegramUser {
|
||||
id: number;
|
||||
is_bot: boolean;
|
||||
first_name: string;
|
||||
last_name?: string;
|
||||
username?: string;
|
||||
language_code?: string;
|
||||
}
|
||||
|
||||
export interface TelegramChat {
|
||||
id: number;
|
||||
type: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// OpenAI Types (Function Calling)
|
||||
// ============================================
|
||||
|
||||
export interface OpenAIToolCall {
|
||||
id: string;
|
||||
type: 'function';
|
||||
function: {
|
||||
name: string;
|
||||
arguments: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface OpenAIMessage {
|
||||
role: 'system' | 'user' | 'assistant' | 'tool';
|
||||
content: string | null;
|
||||
tool_calls?: OpenAIToolCall[];
|
||||
tool_call_id?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface OpenAIChoice {
|
||||
message: OpenAIMessage;
|
||||
finish_reason: string;
|
||||
}
|
||||
|
||||
export interface OpenAIAPIResponse {
|
||||
choices: OpenAIChoice[];
|
||||
}
|
||||
|
||||
export interface ToolDefinition {
|
||||
type: 'function';
|
||||
function: {
|
||||
name: string;
|
||||
description: string;
|
||||
parameters: {
|
||||
type: 'object';
|
||||
properties: Record<string, unknown>;
|
||||
required?: string[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Workers AI Types (Fallback)
|
||||
// ============================================
|
||||
|
||||
export type WorkersAIModel =
|
||||
| "@cf/meta/llama-3.1-8b-instruct"
|
||||
| "@cf/meta/llama-3.2-3b-instruct";
|
||||
|
||||
export interface WorkersAIMessage {
|
||||
role: "system" | "user" | "assistant";
|
||||
content: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// User & Auth Types
|
||||
// ============================================
|
||||
|
||||
export type UserRole = 'admin' | 'user';
|
||||
|
||||
export interface User {
|
||||
id: number;
|
||||
telegram_id: string;
|
||||
username: string | null;
|
||||
first_name: string | null;
|
||||
role: UserRole;
|
||||
language_code: string;
|
||||
context_limit: number;
|
||||
last_active_at: string | null;
|
||||
is_blocked: number;
|
||||
blocked_reason: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Financial Types
|
||||
// ============================================
|
||||
|
||||
export interface Wallet {
|
||||
id: number;
|
||||
user_id: number;
|
||||
balance: number;
|
||||
currency: string;
|
||||
version: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export type TransactionType = 'deposit' | 'withdrawal' | 'refund' | 'charge';
|
||||
export type TransactionStatus = 'pending' | 'confirmed' | 'rejected' | 'cancelled';
|
||||
|
||||
export interface Transaction {
|
||||
id: number;
|
||||
user_id: number;
|
||||
type: TransactionType;
|
||||
amount: number;
|
||||
status: TransactionStatus;
|
||||
depositor_name: string | null;
|
||||
depositor_name_prefix: string | null;
|
||||
description: string | null;
|
||||
reference_type: string | null;
|
||||
reference_id: number | null;
|
||||
confirmed_by: number | null;
|
||||
confirmed_at: string | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface BankNotification {
|
||||
bankName: string;
|
||||
depositorName: string;
|
||||
amount: number;
|
||||
balanceAfter?: number;
|
||||
transactionTime?: Date;
|
||||
rawMessage: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Asset Types
|
||||
// ============================================
|
||||
|
||||
export type DomainStatus = 'active' | 'expired' | 'pending' | 'suspended';
|
||||
|
||||
export interface Domain {
|
||||
id: number;
|
||||
user_id: number;
|
||||
domain: string;
|
||||
status: DomainStatus;
|
||||
registrar: string | null;
|
||||
nameservers: string | null;
|
||||
auto_renew: number;
|
||||
expiry_date: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export type ServerStatus = 'pending' | 'provisioning' | 'running' | 'stopped' | 'terminated' | 'failed';
|
||||
|
||||
export interface Server {
|
||||
id: number;
|
||||
user_id: number;
|
||||
provider: string;
|
||||
instance_id: string | null;
|
||||
label: string | null;
|
||||
ip_address: string | null;
|
||||
region: string | null;
|
||||
spec_label: string | null;
|
||||
monthly_price: number | null;
|
||||
status: ServerStatus;
|
||||
image: string | null;
|
||||
provisioned_at: string | null;
|
||||
terminated_at: string | null;
|
||||
expires_at: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface DdosService {
|
||||
id: number;
|
||||
user_id: number;
|
||||
target: string;
|
||||
protection_level: 'basic' | 'standard' | 'premium';
|
||||
status: 'active' | 'inactive' | 'suspended';
|
||||
provider: string | null;
|
||||
monthly_price: number | null;
|
||||
expiry_date: string | null;
|
||||
}
|
||||
|
||||
export interface VpnService {
|
||||
id: number;
|
||||
user_id: number;
|
||||
protocol: 'wireguard' | 'openvpn' | 'ipsec';
|
||||
status: 'active' | 'inactive' | 'suspended';
|
||||
endpoint: string | null;
|
||||
monthly_price: number | null;
|
||||
expiry_date: string | null;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Support Types
|
||||
// ============================================
|
||||
|
||||
export interface Feedback {
|
||||
id: number;
|
||||
user_id: number;
|
||||
session_type: string;
|
||||
rating: number;
|
||||
comment: string | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export type PendingActionStatus = 'pending' | 'approved' | 'rejected' | 'executed' | 'failed';
|
||||
|
||||
export interface PendingAction {
|
||||
id: number;
|
||||
user_id: number;
|
||||
action_type: string;
|
||||
target: string;
|
||||
params: string;
|
||||
status: PendingActionStatus;
|
||||
approved_by: number | null;
|
||||
created_at: string;
|
||||
executed_at: string | null;
|
||||
}
|
||||
|
||||
export interface AuditLog {
|
||||
id: number;
|
||||
actor_id: number | null;
|
||||
action: string;
|
||||
resource_type: string;
|
||||
resource_id: string | null;
|
||||
details: string | null;
|
||||
result: 'success' | 'failure';
|
||||
request_id: string | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface KnowledgeArticle {
|
||||
id: number;
|
||||
category: string;
|
||||
title: string;
|
||||
content: string;
|
||||
tags: string | null;
|
||||
language: string;
|
||||
is_active: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Agent Session Types
|
||||
// ============================================
|
||||
|
||||
export type OnboardingSessionStatus = 'greeting' | 'gathering' | 'suggesting' | 'completed';
|
||||
|
||||
export interface OnboardingSession {
|
||||
user_id: string;
|
||||
status: OnboardingSessionStatus;
|
||||
collected_info: {
|
||||
purpose?: string;
|
||||
requirements?: string;
|
||||
budget?: string;
|
||||
tech_stack?: string[];
|
||||
};
|
||||
messages: Array<{ role: 'user' | 'assistant'; content: string }>;
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
expires_at: number;
|
||||
}
|
||||
|
||||
export type TroubleshootSessionStatus = 'gathering' | 'diagnosing' | 'suggesting' | 'escalated' | 'completed';
|
||||
|
||||
export interface TroubleshootSession {
|
||||
user_id: string;
|
||||
status: TroubleshootSessionStatus;
|
||||
collected_info: {
|
||||
category?: string;
|
||||
symptoms?: string;
|
||||
environment?: string;
|
||||
errorMessage?: string;
|
||||
affected_service?: string;
|
||||
};
|
||||
messages: Array<{ role: 'user' | 'assistant'; content: string }>;
|
||||
escalation_count: number;
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
expires_at: number;
|
||||
}
|
||||
|
||||
export type AssetSessionStatus = 'idle' | 'viewing' | 'managing' | 'completed';
|
||||
|
||||
export interface AssetSession {
|
||||
user_id: string;
|
||||
status: AssetSessionStatus;
|
||||
collected_info: Record<string, unknown>;
|
||||
messages: Array<{ role: 'user' | 'assistant'; content: string }>;
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
expires_at: number;
|
||||
}
|
||||
|
||||
export type BillingSessionStatus = 'collecting_amount' | 'collecting_name' | 'confirming' | 'completed';
|
||||
|
||||
export interface BillingSession {
|
||||
user_id: string;
|
||||
status: BillingSessionStatus;
|
||||
collected_info: {
|
||||
amount?: number;
|
||||
depositor_name?: string;
|
||||
};
|
||||
messages: Array<{ role: 'user' | 'assistant'; content: string }>;
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
expires_at: number;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Tool Argument Types
|
||||
// ============================================
|
||||
|
||||
export interface ManageDomainArgs {
|
||||
action: 'check' | 'whois' | 'list' | 'info' | 'set_ns' | 'price';
|
||||
domain?: string;
|
||||
nameservers?: string[];
|
||||
tld?: string;
|
||||
}
|
||||
|
||||
export interface ManageWalletArgs {
|
||||
action: 'balance' | 'account' | 'request' | 'history' | 'cancel';
|
||||
depositor_name?: string;
|
||||
amount?: number;
|
||||
transaction_id?: number;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export interface ManageServerArgs {
|
||||
action: 'list' | 'info' | 'start' | 'stop' | 'reboot';
|
||||
server_id?: number;
|
||||
}
|
||||
|
||||
export interface CheckServiceArgs {
|
||||
action: 'status' | 'list';
|
||||
service_type?: 'ddos' | 'vpn' | 'all';
|
||||
service_id?: number;
|
||||
}
|
||||
|
||||
export interface RenderD2Args {
|
||||
source: string;
|
||||
format?: 'svg' | 'png';
|
||||
}
|
||||
|
||||
export interface AdminArgs {
|
||||
action: 'block_user' | 'unblock_user' | 'set_role' | 'broadcast' | 'confirm_deposit' | 'reject_deposit' | 'list_pending';
|
||||
target_user_id?: string;
|
||||
role?: UserRole;
|
||||
message?: string;
|
||||
transaction_id?: number;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export interface ApproveActionArgs {
|
||||
action_id: number;
|
||||
approve: boolean;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Inline Keyboard Data
|
||||
// ============================================
|
||||
|
||||
export interface FeedbackKeyboardData {
|
||||
type: 'feedback';
|
||||
session_type: string;
|
||||
rating: number;
|
||||
}
|
||||
|
||||
export interface ActionApprovalKeyboardData {
|
||||
type: 'action_approval';
|
||||
action_id: number;
|
||||
approve: boolean;
|
||||
}
|
||||
|
||||
export interface EscalationKeyboardData {
|
||||
type: 'escalation';
|
||||
session_id: string;
|
||||
action: 'accept' | 'reject';
|
||||
}
|
||||
|
||||
export type KeyboardCallbackData =
|
||||
| FeedbackKeyboardData
|
||||
| ActionApprovalKeyboardData
|
||||
| EscalationKeyboardData;
|
||||
|
||||
// ============================================
|
||||
// D2 Rendering
|
||||
// ============================================
|
||||
|
||||
export interface D2RenderRequest {
|
||||
source: string;
|
||||
format: 'svg' | 'png';
|
||||
}
|
||||
|
||||
export interface D2RenderResponse {
|
||||
success: boolean;
|
||||
image?: ArrayBuffer;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Request Context
|
||||
// ============================================
|
||||
|
||||
export interface RequestContext {
|
||||
requestId: string;
|
||||
userId?: string;
|
||||
startTime: number;
|
||||
}
|
||||
Reference in New Issue
Block a user