Files
flutter_opencode_client/lib/data/store/opencode_store.dart
root 0f4fe33003 Add Opencode (opencode.ai) integration via SSH tunnel
Features:
- Opencode AI chat interface
- SSH tunnel for secure API communication
- Auto-install Opencode on remote servers
- API key management with server-side storage
- Session history and management
- Integration with flutter_server_box server list
2026-04-03 00:41:32 +08:00

191 lines
5.0 KiB
Dart

import 'dart:convert';
import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/model/opencode/models.dart';
/// Opencode 会话存储
class OpencodeSessionStore {
static const _boxName = 'opencode_sessions';
late final Box<String> _box;
static final OpencodeSessionStore _instance = OpencodeSessionStore._internal();
factory OpencodeSessionStore() => _instance;
OpencodeSessionStore._internal();
Future<void> init() async {
_box = await Hive.openBox<String>(_boxName);
}
Future<void> saveSession(OpencodeSession session) async {
final key = 'session_${session.id}';
await _box.put(key, jsonEncode(session.toJson()));
await _updateSessionList(session.id, add: true);
}
OpencodeSession? getSession(String sessionId) {
final key = 'session_$sessionId';
final data = _box.get(key);
if (data == null) return null;
try {
final json = jsonDecode(data) as Map<String, dynamic>;
return OpencodeSession.fromJson(json);
} catch (e) {
return null;
}
}
Future<void> deleteSession(String sessionId) async {
final key = 'session_$sessionId';
await _box.delete(key);
await _updateSessionList(sessionId, add: false);
}
List<OpencodeSession> getAllSessions() {
final sessionIds = _box.get('session_list')?.split(',') ?? [];
final sessions = <OpencodeSession>[];
for (final id in sessionIds) {
if (id.isEmpty) continue;
final session = getSession(id);
if (session != null) {
sessions.add(session);
}
}
sessions.sort((a, b) => b.updatedAt.compareTo(a.updatedAt));
return sessions;
}
List<OpencodeSession> getSessionsByServer(String serverId) {
return getAllSessions()
.where((s) => s.serverId == serverId)
.toList();
}
Future<void> _updateSessionList(String sessionId, {required bool add}) async {
final listStr = _box.get('session_list') ?? '';
final list = listStr.split(',').where((s) => s.isNotEmpty).toList();
if (add) {
if (!list.contains(sessionId)) {
list.add(sessionId);
}
} else {
list.remove(sessionId);
}
await _box.put('session_list', list.join(','));
}
Future<void> updateSessionMessages(OpencodeSession session) async {
await saveSession(session);
}
Future<void> clearAllSessions() async {
await _box.clear();
}
}
/// Opencode 服务器配置存储
class OpencodeConfigStore {
static const _boxName = 'opencode_configs';
late final Box<String> _box;
static final OpencodeConfigStore _instance = OpencodeConfigStore._internal();
factory OpencodeConfigStore() => _instance;
OpencodeConfigStore._internal();
Future<void> init() async {
_box = await Hive.openBox<String>(_boxName);
}
Future<void> saveConfig(OpencodeServerConfig config) async {
final key = 'config_${config.serverId}';
await _box.put(key, jsonEncode(config.toJson()));
}
OpencodeServerConfig getConfig(String serverId) {
final key = 'config_$serverId';
final data = _box.get(key);
if (data == null) {
return OpencodeServerConfig(serverId: serverId);
}
try {
final json = jsonDecode(data) as Map<String, dynamic>;
return OpencodeServerConfig.fromJson(json);
} catch (e) {
return OpencodeServerConfig(serverId: serverId);
}
}
Future<void> deleteConfig(String serverId) async {
final key = 'config_$serverId';
await _box.delete(key);
}
}
/// Opencode API 密钥存储
class OpencodeKeyStore {
static const _boxName = 'opencode_keys';
late final Box<String> _box;
static final OpencodeKeyStore _instance = OpencodeKeyStore._internal();
factory OpencodeKeyStore() => _instance;
OpencodeKeyStore._internal();
Future<void> init() async {
_box = await Hive.openBox<String>(_boxName);
}
/// 保存服务器 API 密钥
Future<void> saveServerKey(String serverId, {
required String apiKey,
String? description,
}) async {
final key = 'key_$serverId';
final data = jsonEncode({
'server_id': serverId,
'api_key': apiKey, // 注意:这里存储明文密钥
'description': description,
'updated_at': DateTime.now().toIso8601String(),
});
await _box.put(key, data);
}
/// 获取服务器密钥
String? getServerKey(String serverId) {
final key = 'key_$serverId';
final data = _box.get(key);
if (data == null) return null;
try {
final json = jsonDecode(data) as Map<String, dynamic>;
return json['api_key'] as String?;
} catch (e) {
return null;
}
}
/// 获取服务器密钥信息
Map<String, dynamic>? getServerKeyInfo(String serverId) {
final key = 'key_$serverId';
final data = _box.get(key);
if (data == null) return null;
try {
return jsonDecode(data) as Map<String, dynamic>;
} catch (e) {
return null;
}
}
/// 删除服务器密钥
Future<void> deleteServerKey(String serverId) async {
final key = 'key_$serverId';
await _box.delete(key);
}
}