fix: tolerate numeric args from MCP JSON in all kanban commands
Replace fragile 'as String'/'as String?' casts in callAsTool() with string interpolation so that numeric values sent by MCP JSON clients (double instead of String) no longer throw a type cast error. Fixes: type 'double' is not a subtype of type 'String' in type cast Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
0ad1fae213
commit
1e263f08c0
13 changed files with 41 additions and 35 deletions
|
|
@ -35,8 +35,8 @@ class AddCommentCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final id = (args['id'] as String).toUpperCase();
|
||||
final comment = args['comment'] as String;
|
||||
final id = '${args['id']}'.toUpperCase();
|
||||
final comment = '${args['comment']}';
|
||||
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
final store = TicketStore(
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class ArchiveCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final id = (args['id'] as String).toUpperCase();
|
||||
final id = '${args['id']}'.toUpperCase();
|
||||
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
final config = context.config.kanban;
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ class BoardCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final typeFilter = args['type'] as String?;
|
||||
final labelFilter = args['label'] as String?;
|
||||
final milestoneFilter = args['milestone'] as String?;
|
||||
final typeFilter = args['type'] != null ? '${args['type']}' : null;
|
||||
final labelFilter = args['label'] != null ? '${args['label']}' : null;
|
||||
final milestoneFilter = args['milestone'] != null
|
||||
? '${args['milestone']}'
|
||||
: null;
|
||||
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
final config = context.config.kanban;
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ class CreateCommand extends DewCommand with DewToolCommand {
|
|||
final context = await ProjectContext.find(fs: _fs);
|
||||
final config = context.config.kanban;
|
||||
|
||||
final title = args['title'] as String;
|
||||
final typeId = args['type'] as String;
|
||||
final columnArg = args['column'] as String?;
|
||||
final body = args['body'] as String? ?? '';
|
||||
final title = '${args['title']}';
|
||||
final typeId = '${args['type']}';
|
||||
final columnArg = args['column'] != null ? '${args['column']}' : null;
|
||||
final body = args['body'] != null ? '${args['body']}' : '';
|
||||
final milestones = _toStringList(args['milestone']);
|
||||
final labels = _toStringList(args['label']);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class DeleteCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final id = (args['id'] as String).toUpperCase();
|
||||
final id = '${args['id']}'.toUpperCase();
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
final store = TicketStore(
|
||||
kanbanDir: context.dirs.kanban,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class GetCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final id = (args['id'] as String).toUpperCase();
|
||||
final id = '${args['id']}'.toUpperCase();
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
final store = TicketStore(
|
||||
kanbanDir: context.dirs.kanban,
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ class LinkCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final id = (args['id'] as String).toUpperCase();
|
||||
final targetId = (args['target'] as String).toUpperCase();
|
||||
final type = args['type'] as String;
|
||||
final id = '${args['id']}'.toUpperCase();
|
||||
final targetId = '${args['target']}'.toUpperCase();
|
||||
final type = '${args['type']}';
|
||||
|
||||
if (id == targetId)
|
||||
throw ArgumentError('A ticket cannot be linked to itself.');
|
||||
|
|
|
|||
|
|
@ -38,10 +38,12 @@ class ListCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final columnFilter = args['column'] as String?;
|
||||
final typeFilter = args['type'] as String?;
|
||||
final labelFilter = args['label'] as String?;
|
||||
final milestoneFilter = args['milestone'] as String?;
|
||||
final columnFilter = args['column'] != null ? '${args['column']}' : null;
|
||||
final typeFilter = args['type'] != null ? '${args['type']}' : null;
|
||||
final labelFilter = args['label'] != null ? '${args['label']}' : null;
|
||||
final milestoneFilter = args['milestone'] != null
|
||||
? '${args['milestone']}'
|
||||
: null;
|
||||
final includeArchived = args['include-archived'] as bool? ?? false;
|
||||
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ class MoveCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final id = (args['id'] as String).toUpperCase();
|
||||
final column = args['column'] as String;
|
||||
final id = '${args['id']}'.toUpperCase();
|
||||
final column = '${args['column']}';
|
||||
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
final config = context.config.kanban;
|
||||
|
|
|
|||
|
|
@ -46,11 +46,13 @@ class SearchCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final query = (args['query'] as String).toLowerCase();
|
||||
final columnFilter = args['column'] as String?;
|
||||
final typeFilter = args['type'] as String?;
|
||||
final labelFilter = args['label'] as String?;
|
||||
final milestoneFilter = args['milestone'] as String?;
|
||||
final query = '${args['query']}'.toLowerCase();
|
||||
final columnFilter = args['column'] != null ? '${args['column']}' : null;
|
||||
final typeFilter = args['type'] != null ? '${args['type']}' : null;
|
||||
final labelFilter = args['label'] != null ? '${args['label']}' : null;
|
||||
final milestoneFilter = args['milestone'] != null
|
||||
? '${args['milestone']}'
|
||||
: null;
|
||||
final includeArchived = args['include-archived'] as bool? ?? false;
|
||||
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class UnarchiveCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final id = (args['id'] as String).toUpperCase();
|
||||
final id = '${args['id']}'.toUpperCase();
|
||||
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
final config = context.config.kanban;
|
||||
|
|
@ -50,7 +50,7 @@ class UnarchiveCommand extends DewCommand with DewToolCommand {
|
|||
if (ticket == null) throw ArgumentError('Ticket $id not found.');
|
||||
if (ticket.column != 'archive') return '$id is not archived.';
|
||||
|
||||
final columnArg = args['column'] as String?;
|
||||
final columnArg = args['column'] != null ? '${args['column']}' : null;
|
||||
final targetColumn = columnArg ?? config.columns.first.id;
|
||||
if (!config.columns.any((c) => c.id == targetColumn)) {
|
||||
throw ArgumentError(
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ class UnlinkCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final id = (args['id'] as String).toUpperCase();
|
||||
final targetId = (args['target'] as String).toUpperCase();
|
||||
final id = '${args['id']}'.toUpperCase();
|
||||
final targetId = '${args['target']}'.toUpperCase();
|
||||
|
||||
final context = await ProjectContext.find(fs: _fs);
|
||||
final store = TicketStore(
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ class UpdateCommand extends DewCommand with DewToolCommand {
|
|||
|
||||
@override
|
||||
Future<String> callAsTool(Map<String, dynamic> args) async {
|
||||
final id = (args['id'] as String).toUpperCase();
|
||||
final title = args['title'] as String?;
|
||||
final typeId = args['type'] as String?;
|
||||
final column = args['column'] as String?;
|
||||
final body = args['body'] as String?;
|
||||
final id = '${args['id']}'.toUpperCase();
|
||||
final title = args['title'] != null ? '${args['title']}' : null;
|
||||
final typeId = args['type'] != null ? '${args['type']}' : null;
|
||||
final column = args['column'] != null ? '${args['column']}' : null;
|
||||
final body = args['body'] != null ? '${args['body']}' : null;
|
||||
final rawMilestones = args['milestone'] as List?;
|
||||
final milestones = rawMilestones != null && rawMilestones.isNotEmpty
|
||||
? rawMilestones.cast<String>().where((s) => s.isNotEmpty).toList()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue