feat: 优化前端 UI 组件与交互体验
- 优化日历、待办、消息等页面交互 - 更新 ChatBloc 与 UI Schema 渲染 - 优化联系人、首页、设置页面体验
This commit is contained in:
@@ -1,26 +1,15 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'tool_result.dart';
|
||||
|
||||
part 'ag_ui_event.g.dart';
|
||||
|
||||
class AgUiEventTypeWire {
|
||||
static const runStarted = 'RUN_STARTED';
|
||||
static const runFinished = 'RUN_FINISHED';
|
||||
static const runError = 'RUN_ERROR';
|
||||
static const stepStarted = 'STEP_STARTED';
|
||||
static const stepFinished = 'STEP_FINISHED';
|
||||
static const textMessageStart = 'TEXT_MESSAGE_START';
|
||||
static const textMessageContent = 'TEXT_MESSAGE_CONTENT';
|
||||
static const textMessageEnd = 'TEXT_MESSAGE_END';
|
||||
static const toolCallStart = 'TOOL_CALL_START';
|
||||
static const toolCallArgs = 'TOOL_CALL_ARGS';
|
||||
static const toolCallEnd = 'TOOL_CALL_END';
|
||||
static const toolCallResult = 'TOOL_CALL_RESULT';
|
||||
static const toolCallError = 'TOOL_CALL_ERROR';
|
||||
static const stateSnapshot = 'STATE_SNAPSHOT';
|
||||
static const messagesSnapshot = 'MESSAGES_SNAPSHOT';
|
||||
}
|
||||
|
||||
enum AgUiEventType {
|
||||
@@ -29,55 +18,41 @@ enum AgUiEventType {
|
||||
runError,
|
||||
stepStarted,
|
||||
stepFinished,
|
||||
textMessageStart,
|
||||
textMessageContent,
|
||||
textMessageEnd,
|
||||
toolCallStart,
|
||||
toolCallArgs,
|
||||
toolCallEnd,
|
||||
toolCallResult,
|
||||
toolCallError,
|
||||
stateSnapshot,
|
||||
messagesSnapshot,
|
||||
unknown,
|
||||
}
|
||||
|
||||
// wire 类型到枚举的映射
|
||||
const _wireToTypeMap = {
|
||||
AgUiEventTypeWire.runStarted: AgUiEventType.runStarted,
|
||||
AgUiEventTypeWire.runFinished: AgUiEventType.runFinished,
|
||||
AgUiEventTypeWire.runError: AgUiEventType.runError,
|
||||
AgUiEventTypeWire.stepStarted: AgUiEventType.stepStarted,
|
||||
AgUiEventTypeWire.stepFinished: AgUiEventType.stepFinished,
|
||||
AgUiEventTypeWire.textMessageStart: AgUiEventType.textMessageStart,
|
||||
AgUiEventTypeWire.textMessageContent: AgUiEventType.textMessageContent,
|
||||
AgUiEventTypeWire.textMessageEnd: AgUiEventType.textMessageEnd,
|
||||
AgUiEventTypeWire.toolCallStart: AgUiEventType.toolCallStart,
|
||||
AgUiEventTypeWire.toolCallArgs: AgUiEventType.toolCallArgs,
|
||||
AgUiEventTypeWire.toolCallEnd: AgUiEventType.toolCallEnd,
|
||||
AgUiEventTypeWire.toolCallResult: AgUiEventType.toolCallResult,
|
||||
AgUiEventTypeWire.toolCallError: AgUiEventType.toolCallError,
|
||||
AgUiEventTypeWire.stateSnapshot: AgUiEventType.stateSnapshot,
|
||||
AgUiEventTypeWire.messagesSnapshot: AgUiEventType.messagesSnapshot,
|
||||
};
|
||||
|
||||
// 枚举到 wire 类型的映射
|
||||
const _typeToWireMap = {
|
||||
AgUiEventType.runStarted: AgUiEventTypeWire.runStarted,
|
||||
AgUiEventType.runFinished: AgUiEventTypeWire.runFinished,
|
||||
AgUiEventType.runError: AgUiEventTypeWire.runError,
|
||||
AgUiEventType.stepStarted: AgUiEventTypeWire.stepStarted,
|
||||
AgUiEventType.stepFinished: AgUiEventTypeWire.stepFinished,
|
||||
AgUiEventType.textMessageStart: AgUiEventTypeWire.textMessageStart,
|
||||
AgUiEventType.textMessageContent: AgUiEventTypeWire.textMessageContent,
|
||||
AgUiEventType.textMessageEnd: AgUiEventTypeWire.textMessageEnd,
|
||||
AgUiEventType.toolCallStart: AgUiEventTypeWire.toolCallStart,
|
||||
AgUiEventType.toolCallArgs: AgUiEventTypeWire.toolCallArgs,
|
||||
AgUiEventType.toolCallEnd: AgUiEventTypeWire.toolCallEnd,
|
||||
AgUiEventType.toolCallResult: AgUiEventTypeWire.toolCallResult,
|
||||
AgUiEventType.toolCallError: AgUiEventTypeWire.toolCallError,
|
||||
AgUiEventType.stateSnapshot: AgUiEventTypeWire.stateSnapshot,
|
||||
AgUiEventType.messagesSnapshot: AgUiEventTypeWire.messagesSnapshot,
|
||||
AgUiEventType.unknown: '',
|
||||
};
|
||||
|
||||
@@ -86,383 +61,310 @@ AgUiEventType agUiEventTypeFromWire(String wire) =>
|
||||
|
||||
String agUiEventTypeToWire(AgUiEventType type) => _typeToWireMap[type] ?? '';
|
||||
|
||||
// 类型到工厂函数的映射,用于简化 fromJson
|
||||
final _typeToFactory = {
|
||||
AgUiEventType.runStarted: RunStartedEvent.fromJson,
|
||||
AgUiEventType.runFinished: RunFinishedEvent.fromJson,
|
||||
AgUiEventType.runError: RunErrorEvent.fromJson,
|
||||
AgUiEventType.stepStarted: StepStartedEvent.fromJson,
|
||||
AgUiEventType.stepFinished: StepFinishedEvent.fromJson,
|
||||
AgUiEventType.textMessageStart: TextMessageStartEvent.fromJson,
|
||||
AgUiEventType.textMessageContent: TextMessageContentEvent.fromJson,
|
||||
AgUiEventType.textMessageEnd: TextMessageEndEvent.fromJson,
|
||||
AgUiEventType.toolCallStart: ToolCallStartEvent.fromJson,
|
||||
AgUiEventType.toolCallArgs: ToolCallArgsEvent.fromJson,
|
||||
AgUiEventType.toolCallEnd: ToolCallEndEvent.fromJson,
|
||||
AgUiEventType.toolCallResult: ToolCallResultEvent.fromJson,
|
||||
AgUiEventType.toolCallError: ToolCallErrorEvent.fromJson,
|
||||
AgUiEventType.stateSnapshot: StateSnapshotEvent.fromJson,
|
||||
AgUiEventType.messagesSnapshot: MessagesSnapshotEvent.fromJson,
|
||||
AgUiEventType.unknown: UnknownAgUiEvent.fromJson,
|
||||
};
|
||||
abstract class AgUiEvent {
|
||||
const AgUiEvent({required this.type});
|
||||
|
||||
@JsonSerializable(createFactory: false)
|
||||
class AgUiEvent {
|
||||
final AgUiEventType type;
|
||||
|
||||
AgUiEvent({required this.type});
|
||||
|
||||
factory AgUiEvent.fromJson(Map<String, dynamic> json) {
|
||||
final typeStr = json['type'] as String? ?? '';
|
||||
final type = agUiEventTypeFromWire(typeStr);
|
||||
return _typeToFactory[type]?.call(json) ?? UnknownAgUiEvent.fromJson(json);
|
||||
final wireType = json['type'];
|
||||
final type = wireType is String
|
||||
? agUiEventTypeFromWire(wireType)
|
||||
: AgUiEventType.unknown;
|
||||
return switch (type) {
|
||||
AgUiEventType.runStarted => RunStartedEvent.fromJson(json),
|
||||
AgUiEventType.runFinished => RunFinishedEvent.fromJson(json),
|
||||
AgUiEventType.runError => RunErrorEvent.fromJson(json),
|
||||
AgUiEventType.stepStarted => StepStartedEvent.fromJson(json),
|
||||
AgUiEventType.stepFinished => StepFinishedEvent.fromJson(json),
|
||||
AgUiEventType.textMessageEnd => TextMessageEndEvent.fromJson(json),
|
||||
AgUiEventType.toolCallStart => ToolCallStartEvent.fromJson(json),
|
||||
AgUiEventType.toolCallArgs => ToolCallArgsEvent.fromJson(json),
|
||||
AgUiEventType.toolCallEnd => ToolCallEndEvent.fromJson(json),
|
||||
AgUiEventType.toolCallResult => ToolCallResultEvent.fromJson(json),
|
||||
AgUiEventType.toolCallError => ToolCallErrorEvent.fromJson(json),
|
||||
AgUiEventType.unknown => UnknownAgUiEvent(rawJson: json),
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => _$AgUiEventToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable(createFactory: false, createToJson: false)
|
||||
class UnknownAgUiEvent extends AgUiEvent {
|
||||
final Map<String, dynamic> rawJson;
|
||||
|
||||
UnknownAgUiEvent({required this.rawJson})
|
||||
const UnknownAgUiEvent({required this.rawJson})
|
||||
: super(type: AgUiEventType.unknown);
|
||||
|
||||
factory UnknownAgUiEvent.fromJson(Map<String, dynamic> json) =>
|
||||
UnknownAgUiEvent(rawJson: json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => rawJson;
|
||||
final Map<String, dynamic> rawJson;
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class RunStartedEvent extends AgUiEvent {
|
||||
final String threadId;
|
||||
final String runId;
|
||||
|
||||
RunStartedEvent({required this.threadId, required this.runId})
|
||||
: super(type: AgUiEventType.runStarted);
|
||||
|
||||
factory RunStartedEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$RunStartedEventFromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$RunStartedEventToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class RunFinishedEvent extends AgUiEvent {
|
||||
final String threadId;
|
||||
final String runId;
|
||||
|
||||
factory RunStartedEvent.fromJson(Map<String, dynamic> json) =>
|
||||
RunStartedEvent(
|
||||
threadId: _asString(json['threadId']),
|
||||
runId: _asString(json['runId']),
|
||||
);
|
||||
}
|
||||
|
||||
class RunFinishedEvent extends AgUiEvent {
|
||||
RunFinishedEvent({required this.threadId, required this.runId})
|
||||
: super(type: AgUiEventType.runFinished);
|
||||
|
||||
factory RunFinishedEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$RunFinishedEventFromJson(json);
|
||||
final String threadId;
|
||||
final String runId;
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$RunFinishedEventToJson(this);
|
||||
factory RunFinishedEvent.fromJson(Map<String, dynamic> json) =>
|
||||
RunFinishedEvent(
|
||||
threadId: _asString(json['threadId']),
|
||||
runId: _asString(json['runId']),
|
||||
);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class RunErrorEvent extends AgUiEvent {
|
||||
final String message;
|
||||
final String? code;
|
||||
|
||||
RunErrorEvent({required this.message, this.code})
|
||||
: super(type: AgUiEventType.runError);
|
||||
|
||||
factory RunErrorEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$RunErrorEventFromJson(json);
|
||||
final String message;
|
||||
final String? code;
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$RunErrorEventToJson(this);
|
||||
factory RunErrorEvent.fromJson(Map<String, dynamic> json) => RunErrorEvent(
|
||||
message: _asString(json['message'], fallback: 'Unknown error'),
|
||||
code: json['code'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class StepStartedEvent extends AgUiEvent {
|
||||
final String stepName;
|
||||
|
||||
StepStartedEvent({required this.stepName})
|
||||
: super(type: AgUiEventType.stepStarted);
|
||||
|
||||
factory StepStartedEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$StepStartedEventFromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$StepStartedEventToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class StepFinishedEvent extends AgUiEvent {
|
||||
final String stepName;
|
||||
|
||||
factory StepStartedEvent.fromJson(Map<String, dynamic> json) =>
|
||||
StepStartedEvent(stepName: _asString(json['stepName']));
|
||||
}
|
||||
|
||||
class StepFinishedEvent extends AgUiEvent {
|
||||
StepFinishedEvent({required this.stepName})
|
||||
: super(type: AgUiEventType.stepFinished);
|
||||
|
||||
final String stepName;
|
||||
|
||||
factory StepFinishedEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$StepFinishedEventFromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$StepFinishedEventToJson(this);
|
||||
StepFinishedEvent(stepName: _asString(json['stepName']));
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class TextMessageStartEvent extends AgUiEvent {
|
||||
final String messageId;
|
||||
final String role;
|
||||
|
||||
TextMessageStartEvent({required this.messageId, required this.role})
|
||||
: super(type: AgUiEventType.textMessageStart);
|
||||
|
||||
factory TextMessageStartEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$TextMessageStartEventFromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$TextMessageStartEventToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class TextMessageContentEvent extends AgUiEvent {
|
||||
final String messageId;
|
||||
final String delta;
|
||||
|
||||
TextMessageContentEvent({required this.messageId, required this.delta})
|
||||
: super(type: AgUiEventType.textMessageContent);
|
||||
|
||||
factory TextMessageContentEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$TextMessageContentEventFromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$TextMessageContentEventToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class TextMessageEndEvent extends AgUiEvent {
|
||||
final String messageId;
|
||||
TextMessageEndEvent({
|
||||
required this.messageId,
|
||||
required this.answer,
|
||||
required this.role,
|
||||
required this.status,
|
||||
required this.uiSchema,
|
||||
}) : super(type: AgUiEventType.textMessageEnd);
|
||||
|
||||
TextMessageEndEvent({required this.messageId})
|
||||
: super(type: AgUiEventType.textMessageEnd);
|
||||
final String messageId;
|
||||
final String answer;
|
||||
final String role;
|
||||
final String status;
|
||||
final Map<String, dynamic>? uiSchema;
|
||||
|
||||
factory TextMessageEndEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$TextMessageEndEventFromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$TextMessageEndEventToJson(this);
|
||||
TextMessageEndEvent(
|
||||
messageId: _asString(json['messageId']),
|
||||
answer: _asString(json['answer']),
|
||||
role: _asString(json['role'], fallback: 'assistant'),
|
||||
status: _asString(json['status'], fallback: 'success'),
|
||||
uiSchema: _asMap(json['ui_schema']) ?? _asMap(json['uiSchema']),
|
||||
);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ToolCallStartEvent extends AgUiEvent {
|
||||
ToolCallStartEvent({required this.toolCallId, required this.toolCallName})
|
||||
: super(type: AgUiEventType.toolCallStart);
|
||||
|
||||
final String toolCallId;
|
||||
final String toolCallName;
|
||||
final String? parentMessageId;
|
||||
|
||||
ToolCallStartEvent({
|
||||
required this.toolCallId,
|
||||
required this.toolCallName,
|
||||
this.parentMessageId,
|
||||
}) : super(type: AgUiEventType.toolCallStart);
|
||||
|
||||
factory ToolCallStartEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$ToolCallStartEventFromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$ToolCallStartEventToJson(this);
|
||||
ToolCallStartEvent(
|
||||
toolCallId: _asString(json['toolCallId']),
|
||||
toolCallName: _asString(json['toolCallName']),
|
||||
);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ToolCallArgsEvent extends AgUiEvent {
|
||||
final String toolCallId;
|
||||
final String delta;
|
||||
|
||||
ToolCallArgsEvent({required this.toolCallId, required this.delta})
|
||||
ToolCallArgsEvent({required this.toolCallId, required this.args})
|
||||
: super(type: AgUiEventType.toolCallArgs);
|
||||
|
||||
factory ToolCallArgsEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$ToolCallArgsEventFromJson(json);
|
||||
final String toolCallId;
|
||||
final Map<String, dynamic> args;
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$ToolCallArgsEventToJson(this);
|
||||
factory ToolCallArgsEvent.fromJson(Map<String, dynamic> json) =>
|
||||
ToolCallArgsEvent(
|
||||
toolCallId: _asString(json['toolCallId']),
|
||||
args: _asMap(json['args']) ?? const {},
|
||||
);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ToolCallEndEvent extends AgUiEvent {
|
||||
final String toolCallId;
|
||||
|
||||
ToolCallEndEvent({required this.toolCallId})
|
||||
: super(type: AgUiEventType.toolCallEnd);
|
||||
|
||||
factory ToolCallEndEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$ToolCallEndEventFromJson(json);
|
||||
final String toolCallId;
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$ToolCallEndEventToJson(this);
|
||||
factory ToolCallEndEvent.fromJson(Map<String, dynamic> json) =>
|
||||
ToolCallEndEvent(toolCallId: _asString(json['toolCallId']));
|
||||
}
|
||||
|
||||
@JsonSerializable(createFactory: false, createToJson: false)
|
||||
class ToolCallResultEvent extends AgUiEvent {
|
||||
final String messageId;
|
||||
final String toolCallId;
|
||||
final String content;
|
||||
|
||||
ToolCallResultEvent({
|
||||
required this.messageId,
|
||||
required this.toolCallId,
|
||||
required this.content,
|
||||
required this.toolName,
|
||||
required this.resultSummary,
|
||||
required this.status,
|
||||
required this.uiSchema,
|
||||
}) : super(type: AgUiEventType.toolCallResult);
|
||||
|
||||
Map<String, dynamic> get payload {
|
||||
try {
|
||||
final decoded = jsonDecode(content);
|
||||
if (decoded is Map<String, dynamic>) {
|
||||
return decoded;
|
||||
}
|
||||
} catch (_) {}
|
||||
return {'content': content};
|
||||
}
|
||||
final String messageId;
|
||||
final String toolCallId;
|
||||
final String toolName;
|
||||
final String resultSummary;
|
||||
final String status;
|
||||
final Map<String, dynamic>? uiSchema;
|
||||
|
||||
Map<String, dynamic> get result {
|
||||
final rawResult = payload['result'];
|
||||
if (rawResult is Map<String, dynamic>) {
|
||||
return rawResult;
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
UiCard? get ui {
|
||||
final rawUi = payload['ui'];
|
||||
if (rawUi is Map<String, dynamic>) {
|
||||
return UiCard.fromJson(rawUi);
|
||||
}
|
||||
final rawResult = payload['result'];
|
||||
if (rawResult is Map<String, dynamic>) {
|
||||
final type = rawResult['type'];
|
||||
final data = rawResult['data'];
|
||||
if (type is String && data is Map<String, dynamic>) {
|
||||
return UiCard.fromJson(rawResult);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
factory ToolCallResultEvent.fromJson(Map<String, dynamic> json) {
|
||||
final rawContent = json['content'];
|
||||
final hasStructuredFields =
|
||||
json['ui'] != null || json['result'] != null || json['error'] != null;
|
||||
final content = switch (rawContent) {
|
||||
String value when value.trim().startsWith('{') => value,
|
||||
String value when value.trim().startsWith('[') => value,
|
||||
String value when hasStructuredFields => jsonEncode({
|
||||
'toolName': json['toolName'],
|
||||
'result': json['result'],
|
||||
'error': json['error'],
|
||||
'ui': json['ui'],
|
||||
'content': value,
|
||||
}),
|
||||
String value => value,
|
||||
_ => jsonEncode({
|
||||
'toolName': json['toolName'],
|
||||
'result': json['result'],
|
||||
'error': json['error'],
|
||||
'ui': json['ui'],
|
||||
'content': json['content'],
|
||||
}),
|
||||
};
|
||||
final toolCallId =
|
||||
json['toolCallId'] as String? ?? json['callId'] as String? ?? '';
|
||||
final messageId = json['messageId'] as String? ?? 'tool-result-$toolCallId';
|
||||
return ToolCallResultEvent(
|
||||
messageId: messageId,
|
||||
toolCallId: toolCallId,
|
||||
content: content,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => {
|
||||
'type': agUiEventTypeToWire(type),
|
||||
'messageId': messageId,
|
||||
'toolCallId': toolCallId,
|
||||
'content': content,
|
||||
};
|
||||
factory ToolCallResultEvent.fromJson(Map<String, dynamic> json) =>
|
||||
ToolCallResultEvent(
|
||||
messageId: _asString(
|
||||
json['messageId'],
|
||||
fallback: 'tool-${_asString(json['tool_call_id'])}',
|
||||
),
|
||||
toolCallId: _asString(json['tool_call_id'] ?? json['toolCallId']),
|
||||
toolName: _asString(json['tool_name'] ?? json['toolName']),
|
||||
resultSummary: _asString(
|
||||
json['result_summary'] ?? json['resultSummary'],
|
||||
),
|
||||
status: _asString(json['status'], fallback: 'success'),
|
||||
uiSchema: _asMap(json['ui_schema']) ?? _asMap(json['uiSchema']),
|
||||
);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ToolCallErrorEvent extends AgUiEvent {
|
||||
ToolCallErrorEvent({required this.toolCallId, required this.error, this.code})
|
||||
: super(type: AgUiEventType.toolCallError);
|
||||
|
||||
final String toolCallId;
|
||||
final String error;
|
||||
final String? code;
|
||||
|
||||
ToolCallErrorEvent({required this.toolCallId, required this.error, this.code})
|
||||
: super(type: AgUiEventType.toolCallError);
|
||||
|
||||
factory ToolCallErrorEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$ToolCallErrorEventFromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$ToolCallErrorEventToJson(this);
|
||||
ToolCallErrorEvent(
|
||||
toolCallId: _asString(json['toolCallId']),
|
||||
error: _asString(json['error'], fallback: 'Tool call failed'),
|
||||
code: json['code'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@JsonSerializable(createFactory: false, createToJson: false)
|
||||
class StateSnapshotEvent extends AgUiEvent {
|
||||
final Map<String, dynamic> snapshot;
|
||||
|
||||
StateSnapshotEvent({required this.snapshot})
|
||||
: super(type: AgUiEventType.stateSnapshot);
|
||||
|
||||
factory StateSnapshotEvent.fromJson(Map<String, dynamic> json) {
|
||||
final rawSnapshot = json['snapshot'];
|
||||
return StateSnapshotEvent(
|
||||
snapshot: rawSnapshot is Map<String, dynamic>
|
||||
? rawSnapshot
|
||||
: <String, dynamic>{},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => {
|
||||
'type': agUiEventTypeToWire(type),
|
||||
'snapshot': snapshot,
|
||||
};
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class MessagesSnapshotEvent extends AgUiEvent {
|
||||
final List<SnapshotMessage> messages;
|
||||
|
||||
MessagesSnapshotEvent({required this.messages})
|
||||
: super(type: AgUiEventType.messagesSnapshot);
|
||||
|
||||
factory MessagesSnapshotEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$MessagesSnapshotEventFromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$MessagesSnapshotEventToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class SnapshotMessage {
|
||||
final String id;
|
||||
final String role;
|
||||
final String? content;
|
||||
final String? toolCallId;
|
||||
final UiCard? ui;
|
||||
final DateTime? timestamp;
|
||||
final List<Map<String, dynamic>>? attachments;
|
||||
|
||||
SnapshotMessage({
|
||||
required this.id,
|
||||
required this.role,
|
||||
this.content,
|
||||
this.toolCallId,
|
||||
this.ui,
|
||||
this.timestamp,
|
||||
this.attachments,
|
||||
class HistorySnapshot {
|
||||
const HistorySnapshot({
|
||||
required this.scope,
|
||||
required this.threadId,
|
||||
required this.day,
|
||||
required this.hasMore,
|
||||
required this.messages,
|
||||
});
|
||||
|
||||
factory SnapshotMessage.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnapshotMessageFromJson(json);
|
||||
final String scope;
|
||||
final String? threadId;
|
||||
final String? day;
|
||||
final bool hasMore;
|
||||
final List<HistoryMessage> messages;
|
||||
|
||||
Map<String, dynamic> toJson() => _$SnapshotMessageToJson(this);
|
||||
factory HistorySnapshot.fromJson(Map<String, dynamic> json) {
|
||||
final rawMessages = json['messages'];
|
||||
final messages = rawMessages is List
|
||||
? rawMessages
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(HistoryMessage.fromJson)
|
||||
.toList()
|
||||
: const <HistoryMessage>[];
|
||||
return HistorySnapshot(
|
||||
scope: _asString(json['scope'], fallback: 'history_day'),
|
||||
threadId: json['threadId'] as String?,
|
||||
day: json['day'] as String?,
|
||||
hasMore: json['hasMore'] == true,
|
||||
messages: messages,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HistoryMessage {
|
||||
const HistoryMessage({
|
||||
required this.id,
|
||||
required this.seq,
|
||||
required this.role,
|
||||
required this.content,
|
||||
required this.timestamp,
|
||||
this.url,
|
||||
this.uiSchema,
|
||||
});
|
||||
|
||||
final String id;
|
||||
final int seq;
|
||||
final String role;
|
||||
final String content;
|
||||
final DateTime timestamp;
|
||||
final String? url;
|
||||
final Map<String, dynamic>? uiSchema;
|
||||
|
||||
factory HistoryMessage.fromJson(Map<String, dynamic> json) => HistoryMessage(
|
||||
id: _asString(json['id']),
|
||||
seq: _asInt(json['seq']),
|
||||
role: _asString(json['role']),
|
||||
content: _asString(json['content']),
|
||||
timestamp:
|
||||
DateTime.tryParse(_asString(json['timestamp'])) ?? DateTime.now(),
|
||||
url: json['url'] as String?,
|
||||
uiSchema: _asMap(json['ui_schema']) ?? _asMap(json['uiSchema']),
|
||||
);
|
||||
}
|
||||
|
||||
String _asString(Object? value, {String fallback = ''}) {
|
||||
if (value is String) {
|
||||
return value;
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
int _asInt(Object? value) {
|
||||
if (value is int) {
|
||||
return value;
|
||||
}
|
||||
if (value is double) {
|
||||
return value.toInt();
|
||||
}
|
||||
if (value is String) {
|
||||
return int.tryParse(value) ?? 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Map<String, dynamic>? _asMap(Object? value) {
|
||||
if (value is Map<String, dynamic>) {
|
||||
return value;
|
||||
}
|
||||
if (value is Map) {
|
||||
final result = <String, dynamic>{};
|
||||
for (final entry in value.entries) {
|
||||
final key = entry.key;
|
||||
if (key is String) {
|
||||
result[key] = entry.value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user