xworkmate-app/lib/runtime/runtime_models.dart

1011 lines
28 KiB
Dart

import 'dart:convert';
enum RuntimeConnectionMode { unconfigured, local, remote }
extension RuntimeConnectionModeCopy on RuntimeConnectionMode {
String get label => switch (this) {
RuntimeConnectionMode.unconfigured => 'Unconfigured',
RuntimeConnectionMode.local => 'Local',
RuntimeConnectionMode.remote => 'Remote',
};
static RuntimeConnectionMode fromJsonValue(String? value) {
return RuntimeConnectionMode.values.firstWhere(
(item) => item.name == value,
orElse: () => RuntimeConnectionMode.unconfigured,
);
}
}
enum RuntimeConnectionStatus { offline, connecting, connected, error }
extension RuntimeConnectionStatusCopy on RuntimeConnectionStatus {
String get label => switch (this) {
RuntimeConnectionStatus.offline => 'Offline',
RuntimeConnectionStatus.connecting => 'Connecting',
RuntimeConnectionStatus.connected => 'Connected',
RuntimeConnectionStatus.error => 'Error',
};
}
enum AssistantExecutionTarget { local, remote }
extension AssistantExecutionTargetCopy on AssistantExecutionTarget {
String get label => switch (this) {
AssistantExecutionTarget.local => '本地',
AssistantExecutionTarget.remote => '远程',
};
String get promptValue => switch (this) {
AssistantExecutionTarget.local => 'local',
AssistantExecutionTarget.remote => 'remote',
};
static AssistantExecutionTarget fromJsonValue(String? value) {
return AssistantExecutionTarget.values.firstWhere(
(item) => item.name == value,
orElse: () => AssistantExecutionTarget.local,
);
}
}
enum AssistantPermissionLevel { defaultAccess, fullAccess }
extension AssistantPermissionLevelCopy on AssistantPermissionLevel {
String get label => switch (this) {
AssistantPermissionLevel.defaultAccess => '默认权限',
AssistantPermissionLevel.fullAccess => '完全访问权限',
};
String get promptValue => switch (this) {
AssistantPermissionLevel.defaultAccess => 'default',
AssistantPermissionLevel.fullAccess => 'full-access',
};
static AssistantPermissionLevel fromJsonValue(String? value) {
return AssistantPermissionLevel.values.firstWhere(
(item) => item.name == value,
orElse: () => AssistantPermissionLevel.defaultAccess,
);
}
}
class GatewayConnectionProfile {
const GatewayConnectionProfile({
required this.mode,
required this.useSetupCode,
required this.setupCode,
required this.host,
required this.port,
required this.tls,
required this.selectedAgentId,
});
final RuntimeConnectionMode mode;
final bool useSetupCode;
final String setupCode;
final String host;
final int port;
final bool tls;
final String selectedAgentId;
factory GatewayConnectionProfile.defaults() {
return const GatewayConnectionProfile(
mode: RuntimeConnectionMode.remote,
useSetupCode: false,
setupCode: '',
host: 'openclaw.svc.plus',
port: 443,
tls: true,
selectedAgentId: '',
);
}
GatewayConnectionProfile copyWith({
RuntimeConnectionMode? mode,
bool? useSetupCode,
String? setupCode,
String? host,
int? port,
bool? tls,
String? selectedAgentId,
}) {
return GatewayConnectionProfile(
mode: mode ?? this.mode,
useSetupCode: useSetupCode ?? this.useSetupCode,
setupCode: setupCode ?? this.setupCode,
host: host ?? this.host,
port: port ?? this.port,
tls: tls ?? this.tls,
selectedAgentId: selectedAgentId ?? this.selectedAgentId,
);
}
Map<String, dynamic> toJson() {
return {
'mode': mode.name,
'useSetupCode': useSetupCode,
'setupCode': setupCode,
'host': host,
'port': port,
'tls': tls,
'selectedAgentId': selectedAgentId,
};
}
factory GatewayConnectionProfile.fromJson(Map<String, dynamic> json) {
return GatewayConnectionProfile(
mode: RuntimeConnectionModeCopy.fromJsonValue(json['mode'] as String?),
useSetupCode: json['useSetupCode'] as bool? ?? false,
setupCode: json['setupCode'] as String? ?? '',
host: json['host'] as String? ?? GatewayConnectionProfile.defaults().host,
port: json['port'] as int? ?? GatewayConnectionProfile.defaults().port,
tls: json['tls'] as bool? ?? true,
selectedAgentId: json['selectedAgentId'] as String? ?? '',
);
}
}
class OllamaLocalConfig {
const OllamaLocalConfig({
required this.endpoint,
required this.defaultModel,
required this.autoDiscover,
});
final String endpoint;
final String defaultModel;
final bool autoDiscover;
factory OllamaLocalConfig.defaults() {
return const OllamaLocalConfig(
endpoint: 'http://127.0.0.1:11434',
defaultModel: 'qwen2.5-coder:latest',
autoDiscover: true,
);
}
OllamaLocalConfig copyWith({
String? endpoint,
String? defaultModel,
bool? autoDiscover,
}) {
return OllamaLocalConfig(
endpoint: endpoint ?? this.endpoint,
defaultModel: defaultModel ?? this.defaultModel,
autoDiscover: autoDiscover ?? this.autoDiscover,
);
}
Map<String, dynamic> toJson() {
return {
'endpoint': endpoint,
'defaultModel': defaultModel,
'autoDiscover': autoDiscover,
};
}
factory OllamaLocalConfig.fromJson(Map<String, dynamic> json) {
return OllamaLocalConfig(
endpoint:
json['endpoint'] as String? ?? OllamaLocalConfig.defaults().endpoint,
defaultModel:
json['defaultModel'] as String? ??
OllamaLocalConfig.defaults().defaultModel,
autoDiscover: json['autoDiscover'] as bool? ?? true,
);
}
}
class OllamaCloudConfig {
const OllamaCloudConfig({
required this.baseUrl,
required this.organization,
required this.workspace,
required this.defaultModel,
required this.apiKeyRef,
});
final String baseUrl;
final String organization;
final String workspace;
final String defaultModel;
final String apiKeyRef;
factory OllamaCloudConfig.defaults() {
return const OllamaCloudConfig(
baseUrl: 'https://ollama.svc.plus',
organization: '',
workspace: '',
defaultModel: 'gpt-oss:120b',
apiKeyRef: 'ollama_cloud_api_key',
);
}
OllamaCloudConfig copyWith({
String? baseUrl,
String? organization,
String? workspace,
String? defaultModel,
String? apiKeyRef,
}) {
return OllamaCloudConfig(
baseUrl: baseUrl ?? this.baseUrl,
organization: organization ?? this.organization,
workspace: workspace ?? this.workspace,
defaultModel: defaultModel ?? this.defaultModel,
apiKeyRef: apiKeyRef ?? this.apiKeyRef,
);
}
Map<String, dynamic> toJson() {
return {
'baseUrl': baseUrl,
'organization': organization,
'workspace': workspace,
'defaultModel': defaultModel,
'apiKeyRef': apiKeyRef,
};
}
factory OllamaCloudConfig.fromJson(Map<String, dynamic> json) {
return OllamaCloudConfig(
baseUrl:
json['baseUrl'] as String? ?? OllamaCloudConfig.defaults().baseUrl,
organization: json['organization'] as String? ?? '',
workspace: json['workspace'] as String? ?? '',
defaultModel:
json['defaultModel'] as String? ??
OllamaCloudConfig.defaults().defaultModel,
apiKeyRef:
json['apiKeyRef'] as String? ??
OllamaCloudConfig.defaults().apiKeyRef,
);
}
}
class VaultConfig {
const VaultConfig({
required this.address,
required this.namespace,
required this.authMode,
required this.tokenRef,
});
final String address;
final String namespace;
final String authMode;
final String tokenRef;
factory VaultConfig.defaults() {
return const VaultConfig(
address: 'http://127.0.0.1:8200',
namespace: 'default',
authMode: 'token',
tokenRef: 'vault_token',
);
}
VaultConfig copyWith({
String? address,
String? namespace,
String? authMode,
String? tokenRef,
}) {
return VaultConfig(
address: address ?? this.address,
namespace: namespace ?? this.namespace,
authMode: authMode ?? this.authMode,
tokenRef: tokenRef ?? this.tokenRef,
);
}
Map<String, dynamic> toJson() {
return {
'address': address,
'namespace': namespace,
'authMode': authMode,
'tokenRef': tokenRef,
};
}
factory VaultConfig.fromJson(Map<String, dynamic> json) {
return VaultConfig(
address: json['address'] as String? ?? VaultConfig.defaults().address,
namespace:
json['namespace'] as String? ?? VaultConfig.defaults().namespace,
authMode: json['authMode'] as String? ?? VaultConfig.defaults().authMode,
tokenRef: json['tokenRef'] as String? ?? VaultConfig.defaults().tokenRef,
);
}
}
class ApisixYamlProfile {
const ApisixYamlProfile({
required this.name,
required this.sourceType,
required this.filePath,
required this.inlineYaml,
required this.validationState,
required this.validationMessage,
});
final String name;
final String sourceType;
final String filePath;
final String inlineYaml;
final String validationState;
final String validationMessage;
factory ApisixYamlProfile.defaults() {
return const ApisixYamlProfile(
name: 'default',
sourceType: 'workspace-file',
filePath: '/opt/data/apisix/openclaw.yaml',
inlineYaml: '',
validationState: 'idle',
validationMessage: 'Ready to validate',
);
}
ApisixYamlProfile copyWith({
String? name,
String? sourceType,
String? filePath,
String? inlineYaml,
String? validationState,
String? validationMessage,
}) {
return ApisixYamlProfile(
name: name ?? this.name,
sourceType: sourceType ?? this.sourceType,
filePath: filePath ?? this.filePath,
inlineYaml: inlineYaml ?? this.inlineYaml,
validationState: validationState ?? this.validationState,
validationMessage: validationMessage ?? this.validationMessage,
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'sourceType': sourceType,
'filePath': filePath,
'inlineYaml': inlineYaml,
'validationState': validationState,
'validationMessage': validationMessage,
};
}
factory ApisixYamlProfile.fromJson(Map<String, dynamic> json) {
return ApisixYamlProfile(
name: json['name'] as String? ?? ApisixYamlProfile.defaults().name,
sourceType:
json['sourceType'] as String? ??
ApisixYamlProfile.defaults().sourceType,
filePath:
json['filePath'] as String? ?? ApisixYamlProfile.defaults().filePath,
inlineYaml: json['inlineYaml'] as String? ?? '',
validationState:
json['validationState'] as String? ??
ApisixYamlProfile.defaults().validationState,
validationMessage:
json['validationMessage'] as String? ??
ApisixYamlProfile.defaults().validationMessage,
);
}
}
class SettingsSnapshot {
const SettingsSnapshot({
required this.appActive,
required this.launchAtLogin,
required this.showDockIcon,
required this.workspacePath,
required this.remoteProjectRoot,
required this.cliPath,
required this.defaultModel,
required this.defaultProvider,
required this.gateway,
required this.ollamaLocal,
required this.ollamaCloud,
required this.vault,
required this.apisix,
required this.experimentalCanvas,
required this.experimentalBridge,
required this.experimentalDebug,
required this.accountBaseUrl,
required this.accountUsername,
required this.accountWorkspace,
required this.accountLocalMode,
required this.assistantExecutionTarget,
required this.assistantPermissionLevel,
});
final bool appActive;
final bool launchAtLogin;
final bool showDockIcon;
final String workspacePath;
final String remoteProjectRoot;
final String cliPath;
final String defaultModel;
final String defaultProvider;
final GatewayConnectionProfile gateway;
final OllamaLocalConfig ollamaLocal;
final OllamaCloudConfig ollamaCloud;
final VaultConfig vault;
final ApisixYamlProfile apisix;
final bool experimentalCanvas;
final bool experimentalBridge;
final bool experimentalDebug;
final String accountBaseUrl;
final String accountUsername;
final String accountWorkspace;
final bool accountLocalMode;
final AssistantExecutionTarget assistantExecutionTarget;
final AssistantPermissionLevel assistantPermissionLevel;
factory SettingsSnapshot.defaults() {
return SettingsSnapshot(
appActive: true,
launchAtLogin: false,
showDockIcon: true,
workspacePath: '/opt/data',
remoteProjectRoot: '/opt/data/workspace',
cliPath: 'openclaw',
defaultModel: 'gpt-5.4',
defaultProvider: 'gateway',
gateway: GatewayConnectionProfile.defaults(),
ollamaLocal: OllamaLocalConfig.defaults(),
ollamaCloud: OllamaCloudConfig.defaults(),
vault: VaultConfig.defaults(),
apisix: ApisixYamlProfile.defaults(),
experimentalCanvas: false,
experimentalBridge: false,
experimentalDebug: false,
accountBaseUrl: 'https://accounts.svc.plus',
accountUsername: '',
accountWorkspace: 'Default Workspace',
accountLocalMode: true,
assistantExecutionTarget: AssistantExecutionTarget.local,
assistantPermissionLevel: AssistantPermissionLevel.defaultAccess,
);
}
SettingsSnapshot copyWith({
bool? appActive,
bool? launchAtLogin,
bool? showDockIcon,
String? workspacePath,
String? remoteProjectRoot,
String? cliPath,
String? defaultModel,
String? defaultProvider,
GatewayConnectionProfile? gateway,
OllamaLocalConfig? ollamaLocal,
OllamaCloudConfig? ollamaCloud,
VaultConfig? vault,
ApisixYamlProfile? apisix,
bool? experimentalCanvas,
bool? experimentalBridge,
bool? experimentalDebug,
String? accountBaseUrl,
String? accountUsername,
String? accountWorkspace,
bool? accountLocalMode,
AssistantExecutionTarget? assistantExecutionTarget,
AssistantPermissionLevel? assistantPermissionLevel,
}) {
return SettingsSnapshot(
appActive: appActive ?? this.appActive,
launchAtLogin: launchAtLogin ?? this.launchAtLogin,
showDockIcon: showDockIcon ?? this.showDockIcon,
workspacePath: workspacePath ?? this.workspacePath,
remoteProjectRoot: remoteProjectRoot ?? this.remoteProjectRoot,
cliPath: cliPath ?? this.cliPath,
defaultModel: defaultModel ?? this.defaultModel,
defaultProvider: defaultProvider ?? this.defaultProvider,
gateway: gateway ?? this.gateway,
ollamaLocal: ollamaLocal ?? this.ollamaLocal,
ollamaCloud: ollamaCloud ?? this.ollamaCloud,
vault: vault ?? this.vault,
apisix: apisix ?? this.apisix,
experimentalCanvas: experimentalCanvas ?? this.experimentalCanvas,
experimentalBridge: experimentalBridge ?? this.experimentalBridge,
experimentalDebug: experimentalDebug ?? this.experimentalDebug,
accountBaseUrl: accountBaseUrl ?? this.accountBaseUrl,
accountUsername: accountUsername ?? this.accountUsername,
accountWorkspace: accountWorkspace ?? this.accountWorkspace,
accountLocalMode: accountLocalMode ?? this.accountLocalMode,
assistantExecutionTarget:
assistantExecutionTarget ?? this.assistantExecutionTarget,
assistantPermissionLevel:
assistantPermissionLevel ?? this.assistantPermissionLevel,
);
}
Map<String, dynamic> toJson() {
return {
'appActive': appActive,
'launchAtLogin': launchAtLogin,
'showDockIcon': showDockIcon,
'workspacePath': workspacePath,
'remoteProjectRoot': remoteProjectRoot,
'cliPath': cliPath,
'defaultModel': defaultModel,
'defaultProvider': defaultProvider,
'gateway': gateway.toJson(),
'ollamaLocal': ollamaLocal.toJson(),
'ollamaCloud': ollamaCloud.toJson(),
'vault': vault.toJson(),
'apisix': apisix.toJson(),
'experimentalCanvas': experimentalCanvas,
'experimentalBridge': experimentalBridge,
'experimentalDebug': experimentalDebug,
'accountBaseUrl': accountBaseUrl,
'accountUsername': accountUsername,
'accountWorkspace': accountWorkspace,
'accountLocalMode': accountLocalMode,
'assistantExecutionTarget': assistantExecutionTarget.name,
'assistantPermissionLevel': assistantPermissionLevel.name,
};
}
factory SettingsSnapshot.fromJson(Map<String, dynamic> json) {
return SettingsSnapshot(
appActive: json['appActive'] as bool? ?? true,
launchAtLogin: json['launchAtLogin'] as bool? ?? false,
showDockIcon: json['showDockIcon'] as bool? ?? true,
workspacePath:
json['workspacePath'] as String? ??
SettingsSnapshot.defaults().workspacePath,
remoteProjectRoot:
json['remoteProjectRoot'] as String? ??
SettingsSnapshot.defaults().remoteProjectRoot,
cliPath:
json['cliPath'] as String? ?? SettingsSnapshot.defaults().cliPath,
defaultModel:
json['defaultModel'] as String? ??
SettingsSnapshot.defaults().defaultModel,
defaultProvider:
json['defaultProvider'] as String? ??
SettingsSnapshot.defaults().defaultProvider,
gateway: GatewayConnectionProfile.fromJson(
(json['gateway'] as Map?)?.cast<String, dynamic>() ?? const {},
),
ollamaLocal: OllamaLocalConfig.fromJson(
(json['ollamaLocal'] as Map?)?.cast<String, dynamic>() ?? const {},
),
ollamaCloud: OllamaCloudConfig.fromJson(
(json['ollamaCloud'] as Map?)?.cast<String, dynamic>() ?? const {},
),
vault: VaultConfig.fromJson(
(json['vault'] as Map?)?.cast<String, dynamic>() ?? const {},
),
apisix: ApisixYamlProfile.fromJson(
(json['apisix'] as Map?)?.cast<String, dynamic>() ?? const {},
),
experimentalCanvas: json['experimentalCanvas'] as bool? ?? false,
experimentalBridge: json['experimentalBridge'] as bool? ?? false,
experimentalDebug: json['experimentalDebug'] as bool? ?? false,
accountBaseUrl:
json['accountBaseUrl'] as String? ??
SettingsSnapshot.defaults().accountBaseUrl,
accountUsername: json['accountUsername'] as String? ?? '',
accountWorkspace:
json['accountWorkspace'] as String? ??
SettingsSnapshot.defaults().accountWorkspace,
accountLocalMode: json['accountLocalMode'] as bool? ?? true,
assistantExecutionTarget: AssistantExecutionTargetCopy.fromJsonValue(
json['assistantExecutionTarget'] as String?,
),
assistantPermissionLevel: AssistantPermissionLevelCopy.fromJsonValue(
json['assistantPermissionLevel'] as String?,
),
);
}
static SettingsSnapshot fromJsonString(String? raw) {
if (raw == null || raw.trim().isEmpty) {
return SettingsSnapshot.defaults();
}
try {
final decoded = jsonDecode(raw) as Map<String, dynamic>;
return SettingsSnapshot.fromJson(decoded);
} catch (_) {
return SettingsSnapshot.defaults();
}
}
String toJsonString() => jsonEncode(toJson());
}
class GatewayConnectionSnapshot {
const GatewayConnectionSnapshot({
required this.status,
required this.mode,
required this.statusText,
required this.serverName,
required this.remoteAddress,
required this.mainSessionKey,
required this.lastError,
required this.lastConnectedAtMs,
required this.hasSharedAuth,
required this.hasDeviceToken,
required this.healthPayload,
required this.statusPayload,
});
final RuntimeConnectionStatus status;
final RuntimeConnectionMode mode;
final String statusText;
final String? serverName;
final String? remoteAddress;
final String? mainSessionKey;
final String? lastError;
final int? lastConnectedAtMs;
final bool hasSharedAuth;
final bool hasDeviceToken;
final Map<String, dynamic>? healthPayload;
final Map<String, dynamic>? statusPayload;
factory GatewayConnectionSnapshot.initial({
RuntimeConnectionMode mode = RuntimeConnectionMode.unconfigured,
}) {
return GatewayConnectionSnapshot(
status: RuntimeConnectionStatus.offline,
mode: mode,
statusText: 'Offline',
serverName: null,
remoteAddress: null,
mainSessionKey: null,
lastError: null,
lastConnectedAtMs: null,
hasSharedAuth: false,
hasDeviceToken: false,
healthPayload: null,
statusPayload: null,
);
}
GatewayConnectionSnapshot copyWith({
RuntimeConnectionStatus? status,
RuntimeConnectionMode? mode,
String? statusText,
String? serverName,
String? remoteAddress,
String? mainSessionKey,
String? lastError,
int? lastConnectedAtMs,
bool? hasSharedAuth,
bool? hasDeviceToken,
Map<String, dynamic>? healthPayload,
Map<String, dynamic>? statusPayload,
bool clearServerName = false,
bool clearRemoteAddress = false,
bool clearMainSessionKey = false,
bool clearLastError = false,
}) {
return GatewayConnectionSnapshot(
status: status ?? this.status,
mode: mode ?? this.mode,
statusText: statusText ?? this.statusText,
serverName: clearServerName ? null : (serverName ?? this.serverName),
remoteAddress: clearRemoteAddress
? null
: (remoteAddress ?? this.remoteAddress),
mainSessionKey: clearMainSessionKey
? null
: (mainSessionKey ?? this.mainSessionKey),
lastError: clearLastError ? null : (lastError ?? this.lastError),
lastConnectedAtMs: lastConnectedAtMs ?? this.lastConnectedAtMs,
hasSharedAuth: hasSharedAuth ?? this.hasSharedAuth,
hasDeviceToken: hasDeviceToken ?? this.hasDeviceToken,
healthPayload: healthPayload ?? this.healthPayload,
statusPayload: statusPayload ?? this.statusPayload,
);
}
}
class RuntimePackageInfo {
const RuntimePackageInfo({
required this.appName,
required this.packageName,
required this.version,
required this.buildNumber,
});
final String appName;
final String packageName;
final String version;
final String buildNumber;
}
class RuntimeDeviceInfo {
const RuntimeDeviceInfo({
required this.platform,
required this.platformVersion,
required this.deviceFamily,
required this.modelIdentifier,
});
final String platform;
final String platformVersion;
final String deviceFamily;
final String modelIdentifier;
String get platformLabel {
final version = platformVersion.trim();
if (version.isEmpty) {
return platform;
}
return '$platform $version';
}
}
class GatewayAgentSummary {
const GatewayAgentSummary({
required this.id,
required this.name,
required this.emoji,
required this.theme,
});
final String id;
final String name;
final String emoji;
final String theme;
}
class GatewaySessionSummary {
const GatewaySessionSummary({
required this.key,
required this.kind,
required this.displayName,
required this.surface,
required this.subject,
required this.room,
required this.space,
required this.updatedAtMs,
required this.sessionId,
required this.systemSent,
required this.abortedLastRun,
required this.thinkingLevel,
required this.verboseLevel,
required this.inputTokens,
required this.outputTokens,
required this.totalTokens,
required this.model,
required this.contextTokens,
required this.derivedTitle,
required this.lastMessagePreview,
});
final String key;
final String? kind;
final String? displayName;
final String? surface;
final String? subject;
final String? room;
final String? space;
final double? updatedAtMs;
final String? sessionId;
final bool? systemSent;
final bool? abortedLastRun;
final String? thinkingLevel;
final String? verboseLevel;
final int? inputTokens;
final int? outputTokens;
final int? totalTokens;
final String? model;
final int? contextTokens;
final String? derivedTitle;
final String? lastMessagePreview;
String get label {
final candidates = [derivedTitle, displayName, subject, room, space, key];
return candidates.firstWhere(
(item) => item != null && item.trim().isNotEmpty,
orElse: () => key,
)!;
}
}
class GatewayChatMessage {
const GatewayChatMessage({
required this.id,
required this.role,
required this.text,
required this.timestampMs,
required this.toolCallId,
required this.toolName,
required this.stopReason,
required this.pending,
required this.error,
});
final String id;
final String role;
final String text;
final double? timestampMs;
final String? toolCallId;
final String? toolName;
final String? stopReason;
final bool pending;
final bool error;
GatewayChatMessage copyWith({
String? id,
String? role,
String? text,
double? timestampMs,
String? toolCallId,
String? toolName,
String? stopReason,
bool? pending,
bool? error,
}) {
return GatewayChatMessage(
id: id ?? this.id,
role: role ?? this.role,
text: text ?? this.text,
timestampMs: timestampMs ?? this.timestampMs,
toolCallId: toolCallId ?? this.toolCallId,
toolName: toolName ?? this.toolName,
stopReason: stopReason ?? this.stopReason,
pending: pending ?? this.pending,
error: error ?? this.error,
);
}
}
class GatewayInstanceSummary {
const GatewayInstanceSummary({
required this.id,
required this.host,
required this.ip,
required this.version,
required this.platform,
required this.deviceFamily,
required this.modelIdentifier,
required this.lastInputSeconds,
required this.mode,
required this.reason,
required this.text,
required this.timestampMs,
});
final String id;
final String? host;
final String? ip;
final String? version;
final String? platform;
final String? deviceFamily;
final String? modelIdentifier;
final int? lastInputSeconds;
final String? mode;
final String? reason;
final String text;
final double timestampMs;
}
class GatewaySkillSummary {
const GatewaySkillSummary({
required this.name,
required this.description,
required this.source,
required this.skillKey,
required this.primaryEnv,
required this.eligible,
required this.disabled,
required this.missingBins,
required this.missingEnv,
required this.missingConfig,
});
final String name;
final String description;
final String source;
final String skillKey;
final String? primaryEnv;
final bool eligible;
final bool disabled;
final List<String> missingBins;
final List<String> missingEnv;
final List<String> missingConfig;
}
class SecretReferenceEntry {
const SecretReferenceEntry({
required this.name,
required this.provider,
required this.module,
required this.maskedValue,
required this.status,
});
final String name;
final String provider;
final String module;
final String maskedValue;
final String status;
}
class SecretAuditEntry {
const SecretAuditEntry({
required this.timeLabel,
required this.action,
required this.provider,
required this.target,
required this.module,
required this.status,
});
final String timeLabel;
final String action;
final String provider;
final String target;
final String module;
final String status;
Map<String, dynamic> toJson() {
return {
'timeLabel': timeLabel,
'action': action,
'provider': provider,
'target': target,
'module': module,
'status': status,
};
}
factory SecretAuditEntry.fromJson(Map<String, dynamic> json) {
return SecretAuditEntry(
timeLabel: json['timeLabel'] as String? ?? '',
action: json['action'] as String? ?? '',
provider: json['provider'] as String? ?? '',
target: json['target'] as String? ?? '',
module: json['module'] as String? ?? '',
status: json['status'] as String? ?? '',
);
}
}
class DerivedTaskItem {
const DerivedTaskItem({
required this.id,
required this.title,
required this.owner,
required this.status,
required this.surface,
required this.startedAtLabel,
required this.durationLabel,
required this.summary,
required this.sessionKey,
});
final String id;
final String title;
final String owner;
final String status;
final String surface;
final String startedAtLabel;
final String durationLabel;
final String summary;
final String sessionKey;
}
class LocalDeviceIdentity {
const LocalDeviceIdentity({
required this.deviceId,
required this.publicKeyBase64Url,
required this.privateKeyBase64Url,
required this.createdAtMs,
});
final String deviceId;
final String publicKeyBase64Url;
final String privateKeyBase64Url;
final int createdAtMs;
}