fix: pass selected skills with key context
This commit is contained in:
parent
a0667f61c1
commit
9a241349de
@ -424,9 +424,13 @@ extension AppControllerDesktopThreadActions on AppController {
|
||||
resumeSessionHint ||
|
||||
(appendUserTurn &&
|
||||
shouldResumeGatewaySessionForNextSendInternal(sessionKey));
|
||||
final messageWithSkills = messageWithSelectedSkillsContextInternal(
|
||||
message: message,
|
||||
selectedSkillLabels: selectedSkillLabels,
|
||||
);
|
||||
final taskPrompt = taskWorkspaceContextPromptInternal(
|
||||
sessionKey: sessionKey,
|
||||
userPrompt: message,
|
||||
userPrompt: messageWithSkills,
|
||||
workingDirectory: workingDirectory,
|
||||
remoteWorkingDirectoryHint: remoteWorkingDirectoryHint,
|
||||
);
|
||||
@ -493,6 +497,20 @@ extension AppControllerDesktopThreadActions on AppController {
|
||||
}
|
||||
}
|
||||
|
||||
String messageWithSelectedSkillsContextInternal({
|
||||
required String message,
|
||||
required List<String> selectedSkillLabels,
|
||||
}) {
|
||||
final labels = selectedSkillLabels
|
||||
.map((item) => item.trim())
|
||||
.where((item) => item.isNotEmpty)
|
||||
.toList(growable: false);
|
||||
if (labels.isEmpty || message.contains('Preferred skills:')) {
|
||||
return message;
|
||||
}
|
||||
return 'Preferred skills:\n${labels.map((name) => '- $name').join('\n')}\n\n$message';
|
||||
}
|
||||
|
||||
String taskWorkspaceContextPromptInternal({
|
||||
required String sessionKey,
|
||||
required String userPrompt,
|
||||
|
||||
@ -173,7 +173,7 @@ class AssistantTaskRailStateInternal extends State<AssistantTaskRailInternal> {
|
||||
MetaPillInternal(
|
||||
label:
|
||||
'${appText('技能', 'Skills')} ${widget.controller.currentAssistantSkillCount}',
|
||||
icon: Icons.auto_awesome_rounded,
|
||||
icon: Icons.key_rounded,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@ -509,7 +509,7 @@ class ComposerBarStateInternal extends State<ComposerBarInternal> {
|
||||
borderRadius: BorderRadius.circular(AppRadius.chip),
|
||||
onTap: toggleSkillPickerInternal,
|
||||
child: ComposerToolbarChipInternal(
|
||||
icon: Icons.auto_awesome_rounded,
|
||||
icon: Icons.key_rounded,
|
||||
tooltip: skillsTooltipInternal(
|
||||
selectedSkills.length,
|
||||
),
|
||||
|
||||
@ -54,7 +54,7 @@ ComposerSkillOptionInternal skillOptionFromGatewayInternal(
|
||||
label: label,
|
||||
description: description,
|
||||
sourceLabel: sourceLabel,
|
||||
icon: Icons.auto_awesome_rounded,
|
||||
icon: Icons.key_rounded,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -290,7 +290,13 @@ extension AssistantPageStateActionsInternal on AssistantPageStateInternal {
|
||||
option.key: option,
|
||||
};
|
||||
return selectedSkillKeysForInternal(controller)
|
||||
.map((key) => optionsByKey[key]?.label)
|
||||
.map((key) {
|
||||
final option = optionsByKey[key];
|
||||
if (option == null) {
|
||||
return null;
|
||||
}
|
||||
return option.label == key ? key : '${option.label} ($key)';
|
||||
})
|
||||
.whereType<String>()
|
||||
.toList(growable: false);
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:xworkmate/app/app_controller.dart';
|
||||
import 'package:xworkmate/app/app_controller_desktop_external_acp_routing.dart';
|
||||
@ -475,6 +476,47 @@ void main() {
|
||||
expect(option.key, 'browser-fetch');
|
||||
expect(option.label, 'Browser Fetch');
|
||||
expect(option.description, 'Bridge-managed browser skill');
|
||||
expect(option.icon, Icons.key_rounded);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'selected bridge skill is passed to task context with stable key',
|
||||
() async {
|
||||
final fakeGoTaskService = _RecordingGoTaskServiceClient();
|
||||
final controller = _connectedGatewayController(fakeGoTaskService);
|
||||
addTearDown(controller.dispose);
|
||||
controller.skillsControllerInternal.itemsInternal =
|
||||
const <GatewaySkillSummary>[
|
||||
GatewaySkillSummary(
|
||||
name: 'PDF Writer',
|
||||
description: 'Write PDF documents',
|
||||
source: 'openclaw-workspace',
|
||||
skillKey: 'pdf',
|
||||
primaryEnv: null,
|
||||
eligible: true,
|
||||
disabled: false,
|
||||
missingBins: <String>[],
|
||||
missingEnv: <String>[],
|
||||
missingConfig: <String>[],
|
||||
),
|
||||
];
|
||||
await _selectGatewaySession(controller, 'unit-skill-context-task');
|
||||
await controller.toggleAssistantSkillForSession(
|
||||
'unit-skill-context-task',
|
||||
'pdf',
|
||||
);
|
||||
|
||||
await controller.sendChatMessage(
|
||||
'生成 PDF',
|
||||
selectedSkillLabels: const <String>['PDF Writer (pdf)'],
|
||||
);
|
||||
|
||||
expect(fakeGoTaskService.requests, hasLength(1));
|
||||
final request = fakeGoTaskService.requests.single;
|
||||
expect(request.selectedSkills, const <String>['PDF Writer (pdf)']);
|
||||
expect(request.prompt, contains('Preferred skills:'));
|
||||
expect(request.prompt, contains('- PDF Writer (pdf)'));
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user