feat: 重构 memory 系统,支持 user memory 和 work memory 分离

This commit is contained in:
qzl
2026-03-23 14:25:47 +08:00
parent 3aacc756db
commit 6be616f108
70 changed files with 7031 additions and 431 deletions
@@ -0,0 +1,951 @@
class PersonMeta {
final String? source;
final double? confidence;
final DateTime? lastUpdatedAt;
PersonMeta({this.source, this.confidence, this.lastUpdatedAt});
factory PersonMeta.fromJson(Map<String, dynamic>? json) {
if (json == null) return PersonMeta();
return PersonMeta(
source: json['source'] as String?,
confidence: (json['confidence'] as num?)?.toDouble(),
lastUpdatedAt: json['last_updated_at'] != null
? DateTime.parse(json['last_updated_at'] as String)
: null,
);
}
Map<String, dynamic> toJson() => {
'source': source,
'confidence': confidence,
'last_updated_at': lastUpdatedAt?.toIso8601String(),
};
}
class Person {
final String name;
final String? relationship;
final String? role;
final String? preferredContactChannel;
final String? notes;
final PersonMeta? meta;
Person({
required this.name,
this.relationship,
this.role,
this.preferredContactChannel,
this.notes,
this.meta,
});
factory Person.fromJson(Map<String, dynamic> json) {
return Person(
name: json['name'] as String? ?? '',
relationship: json['relationship'] as String?,
role: json['role'] as String?,
preferredContactChannel: json['preferred_contact_channel'] as String?,
notes: json['notes'] as String?,
meta: json['meta'] != null
? PersonMeta.fromJson(json['meta'] as Map<String, dynamic>?)
: null,
);
}
Map<String, dynamic> toJson() => {
'name': name,
'relationship': relationship,
'role': role,
'preferred_contact_channel': preferredContactChannel,
'notes': notes,
'meta': meta?.toJson(),
};
Person copyWith({
String? name,
String? relationship,
String? role,
String? preferredContactChannel,
String? notes,
PersonMeta? meta,
}) {
return Person(
name: name ?? this.name,
relationship: relationship ?? this.relationship,
role: role ?? this.role,
preferredContactChannel:
preferredContactChannel ?? this.preferredContactChannel,
notes: notes ?? this.notes,
meta: meta ?? this.meta,
);
}
}
class PlaceMeta {
final String? source;
final double? confidence;
final DateTime? lastUpdatedAt;
PlaceMeta({this.source, this.confidence, this.lastUpdatedAt});
factory PlaceMeta.fromJson(Map<String, dynamic>? json) {
if (json == null) return PlaceMeta();
return PlaceMeta(
source: json['source'] as String?,
confidence: (json['confidence'] as num?)?.toDouble(),
lastUpdatedAt: json['last_updated_at'] != null
? DateTime.parse(json['last_updated_at'] as String)
: null,
);
}
Map<String, dynamic> toJson() => {
'source': source,
'confidence': confidence,
'last_updated_at': lastUpdatedAt?.toIso8601String(),
};
}
class Place {
final String name;
final String? category;
final String? address;
final String? timezone;
final int? commuteMinutes;
final String? preference;
final String? notes;
final PlaceMeta? meta;
Place({
required this.name,
this.category,
this.address,
this.timezone,
this.commuteMinutes,
this.preference,
this.notes,
this.meta,
});
factory Place.fromJson(Map<String, dynamic> json) {
return Place(
name: json['name'] as String? ?? '',
category: json['category'] as String?,
address: json['address'] as String?,
timezone: json['timezone'] as String?,
commuteMinutes: json['commute_minutes'] as int?,
preference: json['preference'] as String?,
notes: json['notes'] as String?,
meta: json['meta'] != null
? PlaceMeta.fromJson(json['meta'] as Map<String, dynamic>?)
: null,
);
}
Map<String, dynamic> toJson() => {
'name': name,
'category': category,
'address': address,
'timezone': timezone,
'commute_minutes': commuteMinutes,
'preference': preference,
'notes': notes,
'meta': meta?.toJson(),
};
Place copyWith({
String? name,
String? category,
String? address,
String? timezone,
int? commuteMinutes,
String? preference,
String? notes,
PlaceMeta? meta,
}) {
return Place(
name: name ?? this.name,
category: category ?? this.category,
address: address ?? this.address,
timezone: timezone ?? this.timezone,
commuteMinutes: commuteMinutes ?? this.commuteMinutes,
preference: preference ?? this.preference,
notes: notes ?? this.notes,
meta: meta ?? this.meta,
);
}
}
class UserPreferences {
final String? communicationStyle;
final List<String> languagePreference;
final String? locationPreference;
final String? workLifestyle;
final List<String> notificationPreference;
UserPreferences({
this.communicationStyle,
this.languagePreference = const [],
this.locationPreference,
this.workLifestyle,
this.notificationPreference = const [],
});
factory UserPreferences.fromJson(Map<String, dynamic>? json) {
if (json == null) return UserPreferences();
return UserPreferences(
communicationStyle: json['communication_style'] as String?,
languagePreference:
(json['language_preference'] as List<dynamic>?)?.cast<String>() ?? [],
locationPreference: json['location_preference'] as String?,
workLifestyle: json['work_lifestyle'] as String?,
notificationPreference:
(json['notification_preference'] as List<dynamic>?)?.cast<String>() ??
[],
);
}
Map<String, dynamic> toJson() => {
'communication_style': communicationStyle,
'language_preference': languagePreference,
'location_preference': locationPreference,
'work_lifestyle': workLifestyle,
'notification_preference': notificationPreference,
};
UserPreferences copyWith({
String? communicationStyle,
List<String>? languagePreference,
String? locationPreference,
String? workLifestyle,
List<String>? notificationPreference,
}) {
return UserPreferences(
communicationStyle: communicationStyle ?? this.communicationStyle,
languagePreference: languagePreference ?? this.languagePreference,
locationPreference: locationPreference ?? this.locationPreference,
workLifestyle: workLifestyle ?? this.workLifestyle,
notificationPreference:
notificationPreference ?? this.notificationPreference,
);
}
}
class TimeWindow {
final List<String> weekdays;
final String? start;
final String? end;
TimeWindow({this.weekdays = const [], this.start, this.end});
factory TimeWindow.fromJson(Map<String, dynamic> json) {
return TimeWindow(
weekdays: (json['weekdays'] as List<dynamic>?)?.cast<String>() ?? [],
start: json['start'] as String?,
end: json['end'] as String?,
);
}
Map<String, dynamic> toJson() => {
'weekdays': weekdays,
'start': start,
'end': end,
};
}
class SchedulingPreferences {
final List<TimeWindow> productiveWindows;
final List<TimeWindow> preferredMeetingWindows;
final List<TimeWindow> noMeetingWindows;
final List<TimeWindow> deepWorkWindows;
final List<int> preferredMeetingDurationMinutes;
final int? meetingBufferMinutes;
final int? maxMeetingsPerDay;
final String? notes;
SchedulingPreferences({
this.productiveWindows = const [],
this.preferredMeetingWindows = const [],
this.noMeetingWindows = const [],
this.deepWorkWindows = const [],
this.preferredMeetingDurationMinutes = const [30, 60],
this.meetingBufferMinutes,
this.maxMeetingsPerDay,
this.notes,
});
factory SchedulingPreferences.fromJson(Map<String, dynamic>? json) {
if (json == null) return SchedulingPreferences();
return SchedulingPreferences(
productiveWindows:
(json['productive_windows'] as List<dynamic>?)
?.map((e) => TimeWindow.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
preferredMeetingWindows:
(json['preferred_meeting_windows'] as List<dynamic>?)
?.map((e) => TimeWindow.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
noMeetingWindows:
(json['no_meeting_windows'] as List<dynamic>?)
?.map((e) => TimeWindow.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
deepWorkWindows:
(json['deep_work_windows'] as List<dynamic>?)
?.map((e) => TimeWindow.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
preferredMeetingDurationMinutes:
(json['preferred_meeting_duration_minutes'] as List<dynamic>?)
?.cast<int>() ??
[30, 60],
meetingBufferMinutes: json['meeting_buffer_minutes'] as int?,
maxMeetingsPerDay: json['max_meetings_per_day'] as int?,
notes: json['notes'] as String?,
);
}
Map<String, dynamic> toJson() => {
'productive_windows': productiveWindows.map((e) => e.toJson()).toList(),
'preferred_meeting_windows': preferredMeetingWindows
.map((e) => e.toJson())
.toList(),
'no_meeting_windows': noMeetingWindows.map((e) => e.toJson()).toList(),
'deep_work_windows': deepWorkWindows.map((e) => e.toJson()).toList(),
'preferred_meeting_duration_minutes': preferredMeetingDurationMinutes,
'meeting_buffer_minutes': meetingBufferMinutes,
'max_meetings_per_day': maxMeetingsPerDay,
'notes': notes,
};
SchedulingPreferences copyWith({
List<TimeWindow>? productiveWindows,
List<TimeWindow>? preferredMeetingWindows,
List<TimeWindow>? noMeetingWindows,
List<TimeWindow>? deepWorkWindows,
List<int>? preferredMeetingDurationMinutes,
int? meetingBufferMinutes,
int? maxMeetingsPerDay,
String? notes,
}) {
return SchedulingPreferences(
productiveWindows: productiveWindows ?? this.productiveWindows,
preferredMeetingWindows:
preferredMeetingWindows ?? this.preferredMeetingWindows,
noMeetingWindows: noMeetingWindows ?? this.noMeetingWindows,
deepWorkWindows: deepWorkWindows ?? this.deepWorkWindows,
preferredMeetingDurationMinutes:
preferredMeetingDurationMinutes ??
this.preferredMeetingDurationMinutes,
meetingBufferMinutes: meetingBufferMinutes ?? this.meetingBufferMinutes,
maxMeetingsPerDay: maxMeetingsPerDay ?? this.maxMeetingsPerDay,
notes: notes ?? this.notes,
);
}
}
class RecurringRoutineMeta {
final String? source;
final double? confidence;
final DateTime? lastUpdatedAt;
RecurringRoutineMeta({this.source, this.confidence, this.lastUpdatedAt});
factory RecurringRoutineMeta.fromJson(Map<String, dynamic>? json) {
if (json == null) return RecurringRoutineMeta();
return RecurringRoutineMeta(
source: json['source'] as String?,
confidence: (json['confidence'] as num?)?.toDouble(),
lastUpdatedAt: json['last_updated_at'] != null
? DateTime.parse(json['last_updated_at'] as String)
: null,
);
}
Map<String, dynamic> toJson() => {
'source': source,
'confidence': confidence,
'last_updated_at': lastUpdatedAt?.toIso8601String(),
};
}
class RecurringRoutine {
final String name;
final String? description;
final String? cadence;
final List<TimeWindow> timeWindows;
final String? importance;
final RecurringRoutineMeta? meta;
RecurringRoutine({
required this.name,
this.description,
this.cadence,
this.timeWindows = const [],
this.importance,
this.meta,
});
factory RecurringRoutine.fromJson(Map<String, dynamic> json) {
return RecurringRoutine(
name: json['name'] as String? ?? '',
description: json['description'] as String?,
cadence: json['cadence'] as String?,
timeWindows:
(json['time_windows'] as List<dynamic>?)
?.map((e) => TimeWindow.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
importance: json['importance'] as String?,
meta: json['meta'] != null
? RecurringRoutineMeta.fromJson(json['meta'] as Map<String, dynamic>?)
: null,
);
}
Map<String, dynamic> toJson() => {
'name': name,
'description': description,
'cadence': cadence,
'time_windows': timeWindows.map((e) => e.toJson()).toList(),
'importance': importance,
'meta': meta?.toJson(),
};
RecurringRoutine copyWith({
String? name,
String? description,
String? cadence,
List<TimeWindow>? timeWindows,
String? importance,
RecurringRoutineMeta? meta,
}) {
return RecurringRoutine(
name: name ?? this.name,
description: description ?? this.description,
cadence: cadence ?? this.cadence,
timeWindows: timeWindows ?? this.timeWindows,
importance: importance ?? this.importance,
meta: meta ?? this.meta,
);
}
}
class UserMemoryContent {
final String? occupation;
final String? timezone;
final String? primaryLanguage;
final List<Person> people;
final List<Place> places;
final UserPreferences preferences;
final SchedulingPreferences schedulingPreferences;
final List<String> interests;
final List<String> avoidTopics;
final List<String> customRules;
final List<RecurringRoutine> recurringRoutines;
UserMemoryContent({
this.occupation,
this.timezone,
this.primaryLanguage,
this.people = const [],
this.places = const [],
UserPreferences? preferences,
SchedulingPreferences? schedulingPreferences,
this.interests = const [],
this.avoidTopics = const [],
this.customRules = const [],
this.recurringRoutines = const [],
}) : preferences = preferences ?? UserPreferences(),
schedulingPreferences = schedulingPreferences ?? SchedulingPreferences();
factory UserMemoryContent.fromJson(Map<String, dynamic>? json) {
if (json == null) return UserMemoryContent();
return UserMemoryContent(
occupation: json['occupation'] as String?,
timezone: json['timezone'] as String?,
primaryLanguage: json['primary_language'] as String?,
people:
(json['people'] as List<dynamic>?)
?.map((e) => Person.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
places:
(json['places'] as List<dynamic>?)
?.map((e) => Place.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
preferences: UserPreferences.fromJson(
json['preferences'] as Map<String, dynamic>?,
),
schedulingPreferences: SchedulingPreferences.fromJson(
json['scheduling_preferences'] as Map<String, dynamic>?,
),
interests: (json['interests'] as List<dynamic>?)?.cast<String>() ?? [],
avoidTopics:
(json['avoid_topics'] as List<dynamic>?)?.cast<String>() ?? [],
customRules:
(json['custom_rules'] as List<dynamic>?)?.cast<String>() ?? [],
recurringRoutines:
(json['recurring_routines'] as List<dynamic>?)
?.map((e) => RecurringRoutine.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
);
}
Map<String, dynamic> toJson() => {
'occupation': occupation,
'timezone': timezone,
'primary_language': primaryLanguage,
'people': people.map((e) => e.toJson()).toList(),
'places': places.map((e) => e.toJson()).toList(),
'preferences': preferences.toJson(),
'scheduling_preferences': schedulingPreferences.toJson(),
'interests': interests,
'avoid_topics': avoidTopics,
'custom_rules': customRules,
'recurring_routines': recurringRoutines.map((e) => e.toJson()).toList(),
};
UserMemoryContent copyWith({
String? occupation,
String? timezone,
String? primaryLanguage,
List<Person>? people,
List<Place>? places,
UserPreferences? preferences,
SchedulingPreferences? schedulingPreferences,
List<String>? interests,
List<String>? avoidTopics,
List<String>? customRules,
List<RecurringRoutine>? recurringRoutines,
}) {
return UserMemoryContent(
occupation: occupation ?? this.occupation,
timezone: timezone ?? this.timezone,
primaryLanguage: primaryLanguage ?? this.primaryLanguage,
people: people ?? this.people,
places: places ?? this.places,
preferences: preferences ?? this.preferences,
schedulingPreferences:
schedulingPreferences ?? this.schedulingPreferences,
interests: interests ?? this.interests,
avoidTopics: avoidTopics ?? this.avoidTopics,
customRules: customRules ?? this.customRules,
recurringRoutines: recurringRoutines ?? this.recurringRoutines,
);
}
String get summary {
final parts = <String>[];
if (occupation != null && occupation!.isNotEmpty) {
parts.add(occupation!);
}
if (people.isNotEmpty) {
parts.add('${people.length} 位联系人');
}
if (places.isNotEmpty) {
parts.add('${places.length} 个地点');
}
if (interests.isNotEmpty) {
parts.add('${interests.length} 个兴趣');
}
return parts.isEmpty ? '暂无信息' : parts.join(' · ');
}
}
class KeyMilestone {
final String name;
final DateTime? dueDate;
final String? status;
final String? notes;
KeyMilestone({required this.name, this.dueDate, this.status, this.notes});
factory KeyMilestone.fromJson(Map<String, dynamic> json) {
return KeyMilestone(
name: json['name'] as String? ?? '',
dueDate: json['due_date'] != null
? DateTime.parse(json['due_date'] as String)
: null,
status: json['status'] as String?,
notes: json['notes'] as String?,
);
}
Map<String, dynamic> toJson() => {
'name': name,
'due_date': dueDate?.toIso8601String().split('T').first,
'status': status,
'notes': notes,
};
}
class CurrentProject {
final String name;
final String? description;
final String? status;
final String? priority;
final DateTime? deadline;
final List<String> collaborators;
final List<KeyMilestone> keyMilestones;
final String? notes;
CurrentProject({
required this.name,
this.description,
this.status,
this.priority,
this.deadline,
this.collaborators = const [],
this.keyMilestones = const [],
this.notes,
});
factory CurrentProject.fromJson(Map<String, dynamic> json) {
return CurrentProject(
name: json['name'] as String? ?? '',
description: json['description'] as String?,
status: json['status'] as String?,
priority: json['priority'] as String?,
deadline: json['deadline'] != null
? DateTime.parse(json['deadline'] as String)
: null,
collaborators:
(json['collaborators'] as List<dynamic>?)?.cast<String>() ?? [],
keyMilestones:
(json['key_milestones'] as List<dynamic>?)
?.map((e) => KeyMilestone.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
notes: json['notes'] as String?,
);
}
Map<String, dynamic> toJson() => {
'name': name,
'description': description,
'status': status,
'priority': priority,
'deadline': deadline?.toIso8601String().split('T').first,
'collaborators': collaborators,
'key_milestones': keyMilestones.map((e) => e.toJson()).toList(),
'notes': notes,
};
CurrentProject copyWith({
String? name,
String? description,
String? status,
String? priority,
DateTime? deadline,
List<String>? collaborators,
List<KeyMilestone>? keyMilestones,
String? notes,
}) {
return CurrentProject(
name: name ?? this.name,
description: description ?? this.description,
status: status ?? this.status,
priority: priority ?? this.priority,
deadline: deadline ?? this.deadline,
collaborators: collaborators ?? this.collaborators,
keyMilestones: keyMilestones ?? this.keyMilestones,
notes: notes ?? this.notes,
);
}
}
class WorkHabits {
final List<TimeWindow> availableHours;
final List<TimeWindow> deepWorkBlocks;
final List<TimeWindow> preferredMeetingWindows;
final List<TimeWindow> noMeetingWindows;
final List<int> preferredMeetingDurationMinutes;
final String? notificationChannel;
final String? notes;
WorkHabits({
this.availableHours = const [],
this.deepWorkBlocks = const [],
this.preferredMeetingWindows = const [],
this.noMeetingWindows = const [],
this.preferredMeetingDurationMinutes = const [30, 60],
this.notificationChannel,
this.notes,
});
factory WorkHabits.fromJson(Map<String, dynamic>? json) {
if (json == null) return WorkHabits();
return WorkHabits(
availableHours:
(json['available_hours'] as List<dynamic>?)
?.map((e) => TimeWindow.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
deepWorkBlocks:
(json['deep_work_blocks'] as List<dynamic>?)
?.map((e) => TimeWindow.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
preferredMeetingWindows:
(json['preferred_meeting_windows'] as List<dynamic>?)
?.map((e) => TimeWindow.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
noMeetingWindows:
(json['no_meeting_windows'] as List<dynamic>?)
?.map((e) => TimeWindow.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
preferredMeetingDurationMinutes:
(json['preferred_meeting_duration_minutes'] as List<dynamic>?)
?.cast<int>() ??
[30, 60],
notificationChannel: json['notification_channel'] as String?,
notes: json['notes'] as String?,
);
}
Map<String, dynamic> toJson() => {
'available_hours': availableHours.map((e) => e.toJson()).toList(),
'deep_work_blocks': deepWorkBlocks.map((e) => e.toJson()).toList(),
'preferred_meeting_windows': preferredMeetingWindows
.map((e) => e.toJson())
.toList(),
'no_meeting_windows': noMeetingWindows.map((e) => e.toJson()).toList(),
'preferred_meeting_duration_minutes': preferredMeetingDurationMinutes,
'notification_channel': notificationChannel,
'notes': notes,
};
WorkHabits copyWith({
List<TimeWindow>? availableHours,
List<TimeWindow>? deepWorkBlocks,
List<TimeWindow>? preferredMeetingWindows,
List<TimeWindow>? noMeetingWindows,
List<int>? preferredMeetingDurationMinutes,
String? notificationChannel,
String? notes,
}) {
return WorkHabits(
availableHours: availableHours ?? this.availableHours,
deepWorkBlocks: deepWorkBlocks ?? this.deepWorkBlocks,
preferredMeetingWindows:
preferredMeetingWindows ?? this.preferredMeetingWindows,
noMeetingWindows: noMeetingWindows ?? this.noMeetingWindows,
preferredMeetingDurationMinutes:
preferredMeetingDurationMinutes ??
this.preferredMeetingDurationMinutes,
notificationChannel: notificationChannel ?? this.notificationChannel,
notes: notes ?? this.notes,
);
}
}
class TeamMemberMeta {
final String? source;
final double? confidence;
final DateTime? lastUpdatedAt;
TeamMemberMeta({this.source, this.confidence, this.lastUpdatedAt});
factory TeamMemberMeta.fromJson(Map<String, dynamic>? json) {
if (json == null) return TeamMemberMeta();
return TeamMemberMeta(
source: json['source'] as String?,
confidence: (json['confidence'] as num?)?.toDouble(),
lastUpdatedAt: json['last_updated_at'] != null
? DateTime.parse(json['last_updated_at'] as String)
: null,
);
}
Map<String, dynamic> toJson() => {
'source': source,
'confidence': confidence,
'last_updated_at': lastUpdatedAt?.toIso8601String(),
};
}
class TeamMember {
final String name;
final String? role;
final String? relationship;
final String? preferredContactChannel;
final String? notes;
final TeamMemberMeta? meta;
TeamMember({
required this.name,
this.role,
this.relationship,
this.preferredContactChannel,
this.notes,
this.meta,
});
factory TeamMember.fromJson(Map<String, dynamic> json) {
return TeamMember(
name: json['name'] as String? ?? '',
role: json['role'] as String?,
relationship: json['relationship'] as String?,
preferredContactChannel: json['preferred_contact_channel'] as String?,
notes: json['notes'] as String?,
meta: json['meta'] != null
? TeamMemberMeta.fromJson(json['meta'] as Map<String, dynamic>?)
: null,
);
}
Map<String, dynamic> toJson() => {
'name': name,
'role': role,
'relationship': relationship,
'preferred_contact_channel': preferredContactChannel,
'notes': notes,
'meta': meta?.toJson(),
};
TeamMember copyWith({
String? name,
String? role,
String? relationship,
String? preferredContactChannel,
String? notes,
TeamMemberMeta? meta,
}) {
return TeamMember(
name: name ?? this.name,
role: role ?? this.role,
relationship: relationship ?? this.relationship,
preferredContactChannel:
preferredContactChannel ?? this.preferredContactChannel,
notes: notes ?? this.notes,
meta: meta ?? this.meta,
);
}
}
class WorkProfileContent {
final String? occupation;
final List<String> expertise;
final List<String> preferredTools;
final List<CurrentProject> currentProjects;
final WorkHabits workHabits;
final List<TeamMember> teamMembers;
final String? teamContext;
final List<String> workRules;
WorkProfileContent({
this.occupation,
this.expertise = const [],
this.preferredTools = const [],
this.currentProjects = const [],
WorkHabits? workHabits,
this.teamMembers = const [],
this.teamContext,
this.workRules = const [],
}) : workHabits = workHabits ?? WorkHabits();
factory WorkProfileContent.fromJson(Map<String, dynamic>? json) {
if (json == null) return WorkProfileContent();
return WorkProfileContent(
occupation: json['occupation'] as String?,
expertise: (json['expertise'] as List<dynamic>?)?.cast<String>() ?? [],
preferredTools:
(json['preferred_tools'] as List<dynamic>?)?.cast<String>() ?? [],
currentProjects:
(json['current_projects'] as List<dynamic>?)
?.map((e) => CurrentProject.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
workHabits: WorkHabits.fromJson(
json['work_habits'] as Map<String, dynamic>?,
),
teamMembers:
(json['team_members'] as List<dynamic>?)
?.map((e) => TeamMember.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
teamContext: json['team_context'] as String?,
workRules: (json['work_rules'] as List<dynamic>?)?.cast<String>() ?? [],
);
}
Map<String, dynamic> toJson() => {
'occupation': occupation,
'expertise': expertise,
'preferred_tools': preferredTools,
'current_projects': currentProjects.map((e) => e.toJson()).toList(),
'work_habits': workHabits.toJson(),
'team_members': teamMembers.map((e) => e.toJson()).toList(),
'team_context': teamContext,
'work_rules': workRules,
};
WorkProfileContent copyWith({
String? occupation,
List<String>? expertise,
List<String>? preferredTools,
List<CurrentProject>? currentProjects,
WorkHabits? workHabits,
List<TeamMember>? teamMembers,
String? teamContext,
List<String>? workRules,
}) {
return WorkProfileContent(
occupation: occupation ?? this.occupation,
expertise: expertise ?? this.expertise,
preferredTools: preferredTools ?? this.preferredTools,
currentProjects: currentProjects ?? this.currentProjects,
workHabits: workHabits ?? this.workHabits,
teamMembers: teamMembers ?? this.teamMembers,
teamContext: teamContext ?? this.teamContext,
workRules: workRules ?? this.workRules,
);
}
String get summary {
final parts = <String>[];
if (occupation != null && occupation!.isNotEmpty) {
parts.add(occupation!);
}
if (expertise.isNotEmpty) {
parts.add('${expertise.length} 项专长');
}
if (currentProjects.isNotEmpty) {
parts.add('${currentProjects.length} 个项目');
}
if (teamMembers.isNotEmpty) {
parts.add('${teamMembers.length} 位团队成员');
}
return parts.isEmpty ? '暂无信息' : parts.join(' · ');
}
}
class MemoryListResponse {
final UserMemoryContent? userMemory;
final WorkProfileContent? workMemory;
MemoryListResponse({this.userMemory, this.workMemory});
factory MemoryListResponse.fromJson(Map<String, dynamic> json) {
return MemoryListResponse(
userMemory: json['user_memory'] != null
? UserMemoryContent.fromJson(
json['user_memory'] as Map<String, dynamic>?,
)
: null,
workMemory: json['work_memory'] != null
? WorkProfileContent.fromJson(
json['work_memory'] as Map<String, dynamic>?,
)
: null,
);
}
}