refactor: clean CLI taxonomy — canonical subcommands, merged memory.update, no aliases

- calendar: split write → create/read/update/delete/share
- contacts: rename lookup → read
- memory: merge write+forget → update (unified action field in operations)
- Remove all alias/normalization logic from adapter and handlers
- Update tool_postprocessor ui_hints builders to canonical keys
- Remove frontend legacy TOOL_CALL_START/ARGS/END events and ToolCallItem
- Update SKILL.md files and protocol docs
- Update tests and settings screens
This commit is contained in:
qzl
2026-04-23 12:12:41 +08:00
parent 91077a933d
commit 19e273a9e6
48 changed files with 1578 additions and 811 deletions
@@ -4,9 +4,7 @@ import 'package:flutter/material.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:social_app/core/chat/chat_list_item.dart';
import '../../../../core/l10n/l10n.dart';
import '../../../../core/theme/design_tokens.dart';
import '../../../../core/utils/tool_name_localizer.dart';
import '../../../../shared/widgets/app_loading_indicator.dart';
import '../../../../shared/widgets/ui_schema/ui_schema_renderer.dart';
@@ -21,18 +19,28 @@ const _toolResultWidthFactor = 0.88;
const _iconSize = AppSpacing.xxl;
class HomeChatItemRenderer {
static Widget build(BuildContext context, ChatListItem item) {
static Widget build(
BuildContext context,
ChatListItem item, {
ValueChanged<String>? onSuggestedActionTap,
}) {
switch (item.type) {
case ChatItemType.message:
return _buildMessageItem(context, item as TextMessageItem);
case ChatItemType.toolCall:
return _buildToolCallItem(context, item as ToolCallItem);
return _buildMessageItem(
context,
item as TextMessageItem,
onSuggestedActionTap: onSuggestedActionTap,
);
case ChatItemType.toolResult:
return _buildToolResultItem(context, item as ToolResultItem);
}
}
static Widget _buildMessageItem(BuildContext context, TextMessageItem item) {
static Widget _buildMessageItem(
BuildContext context,
TextMessageItem item, {
ValueChanged<String>? onSuggestedActionTap,
}) {
final colorScheme = Theme.of(context).colorScheme;
final isUser = item.sender == MessageSender.user;
final maxMessageWidth =
@@ -41,6 +49,11 @@ class HomeChatItemRenderer {
item.attachments,
);
final hasRenderableAttachments = imageAttachments.isNotEmpty;
final suggestedActionTap = onSuggestedActionTap;
final shouldRenderSuggestions =
!isUser &&
item.suggestedActions.isNotEmpty &&
suggestedActionTap != null;
return Column(
crossAxisAlignment: isUser
? CrossAxisAlignment.end
@@ -98,6 +111,29 @@ class HomeChatItemRenderer {
imageAttachments: imageAttachments,
),
),
if (shouldRenderSuggestions)
Padding(
padding: const EdgeInsets.only(top: AppSpacing.xs),
child: Wrap(
spacing: AppSpacing.sm,
runSpacing: AppSpacing.xs,
children: item.suggestedActions
.map(
(action) => GestureDetector(
onTap: () => suggestedActionTap(action),
child: Text(
action,
style: TextStyle(
fontSize: 12,
color: colorScheme.primary,
fontWeight: FontWeight.w500,
),
),
),
)
.toList(),
),
),
],
);
}
@@ -221,83 +257,6 @@ class HomeChatItemRenderer {
);
}
static Widget _buildToolCallItem(BuildContext context, ToolCallItem item) {
final l10n = context.l10n;
final colorScheme = Theme.of(context).colorScheme;
final (statusText, statusColor, statusIcon) = switch (item.status) {
ToolCallStatus.pending => (
l10n.homeToolPreparing,
colorScheme.onSurfaceVariant,
LucideIcons.clock,
),
ToolCallStatus.executing => (
l10n.homeToolExecuting,
colorScheme.primary,
LucideIcons.loader,
),
ToolCallStatus.error => (
item.errorMessage ?? l10n.homeToolExecutionFailed,
colorScheme.error,
LucideIcons.alertCircle,
),
ToolCallStatus.completed => (
l10n.homeToolCompleted,
colorScheme.tertiary,
LucideIcons.checkCircle,
),
};
return Container(
width: double.infinity,
padding: const EdgeInsets.all(AppSpacing.md),
decoration: BoxDecoration(
color: colorScheme.surfaceContainerLow,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(color: colorScheme.outlineVariant),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 28,
height: 28,
decoration: BoxDecoration(
color: colorScheme.surface,
borderRadius: BorderRadius.circular(AppRadius.full),
border: Border.all(color: colorScheme.outlineVariant),
),
child: Icon(statusIcon, size: 14, color: statusColor),
),
const SizedBox(width: AppSpacing.sm),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
localizeToolName(item.toolName),
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w700,
color: colorScheme.onSurface,
),
),
const SizedBox(height: AppSpacing.xs),
Text(
statusText,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: statusColor,
),
),
],
),
),
],
),
);
}
static Widget _buildToolResultItem(
BuildContext context,
ToolResultItem item,