computeTool function

Future<Map<String, Object?>> computeTool(
  1. String name,
  2. Map<String, Object?> args,
  3. McpLimits limits
)

Runs the tool named name with args and returns its JSON result map.

The returned map always contains an isError flag. This function is pure with respect to the host (no shared state), so it can run either in-process or inside a spawned isolate (see runtime/isolate_executor.dart).

Implementation

Future<Map<String, Object?>> computeTool(
  String name,
  Map<String, Object?> args,
  McpLimits limits,
) async {
  if (isLspTool(name)) return computeLspTool(name, args, limits);

  final rt = ApolloRuntime(limits: limits);

  switch (name) {
    case parseToolName:
      final o = await rt.parse(_str(args, 'language'), _str(args, 'source'));
      final root = o.root;
      return <String, Object?>{
        'ok': root != null,
        'diagnostics': o.diagnostics,
        if (root != null)
          'summary': <String, Object?>{
            'namespace': root.namespace,
            'classes': root.classesNames,
            'functions': root.functions.map((f) => f.name).toList(),
            'imports': root.imports.map((i) => i.path).toList(),
          },
        'isError': root == null,
      };

    case astToolName:
      final o = await rt.parse(_str(args, 'language'), _str(args, 'source'));
      if (o.root == null) {
        return <String, Object?>{'diagnostics': o.diagnostics, 'isError': true};
      }
      final requested = (args['maxDepth'] as int?) ?? limits.maxAstDepth;
      final depth = math.min(requested, limits.maxAstDepth);
      return <String, Object?>{
        'ast': astNodeToJson(o.root!, maxDepth: depth),
        'isError': false,
      };

    case symbolsToolName:
      final o = await rt.parse(_str(args, 'language'), _str(args, 'source'));
      if (o.root == null) {
        return <String, Object?>{'diagnostics': o.diagnostics, 'isError': true};
      }
      return <String, Object?>{
        'symbols': symbolsToJson(o.root!),
        'isError': false,
      };

    case typesToolName:
      final o = await rt.parse(_str(args, 'language'), _str(args, 'source'));
      if (o.root == null) {
        return <String, Object?>{'diagnostics': o.diagnostics, 'isError': true};
      }
      return <String, Object?>{...typesToJson(o.root!), 'isError': false};

    case executeToolName:
      final rawArgs = (args['args'] as List?)?.cast<Object?>() ?? const [];
      final o = await rt.execute(
        _str(args, 'language'),
        _str(args, 'source'),
        function: _str(args, 'function', 'main'),
        className: args['className'] as String?,
        args: rawArgs,
        timeoutMs: args['timeoutMs'] as int?,
      );
      return <String, Object?>{
        'result': o.result,
        'hasResult': o.hasResult,
        'output': o.output,
        'truncated': o.truncated,
        'diagnostics': o.diagnostics,
        'isError': o.diagnostics.isNotEmpty,
      };

    case translateToolName:
      final o = await rt.translate(
        _str(args, 'from'),
        _str(args, 'to'),
        _str(args, 'source'),
      );
      return <String, Object?>{
        'generated': o.generated,
        'diagnostics': o.diagnostics,
        'isError': o.generated == null,
      };

    case wasmToolName:
      final o = await rt.compileWasm(
        _str(args, 'language'),
        _str(args, 'source'),
      );
      return <String, Object?>{
        'modules': o.modules,
        'diagnostics': o.diagnostics,
        'isError': o.modules == null,
      };

    default:
      return <String, Object?>{
        'diagnostics': [
          <String, Object?>{
            'severity': 'error',
            'message': 'Unknown tool: $name',
          },
        ],
        'isError': true,
      };
  }
}