Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON-RPC API: Understanding V1 vs V2, calling Flow APIs from plugins #87

Open
2 tasks done
cspotcode opened this issue Oct 12, 2024 · 13 comments
Open
2 tasks done
Labels
bug Something isn't working

Comments

@cspotcode
Copy link

cspotcode commented Oct 12, 2024

Checks

  • I have checked that this issue has not already been reported.

  • I am using the latest version of Flow Launcher.

Problem Description

The docs for JSON-RPC appear inaccurate or misleading in three ways: https://www.flowlauncher.com/docs/#/json-rpc

  1. The dataflow --> and <-- is backwards. "Query" is sent from flow to the plugin. Title/Subtitle/IconPath is sent from the plugin to Flow.
  2. The example response from Plugin to Flow is incorrect. Should be:
-<-- {"Title": "title", "SubTitle": "sub title", "IconPath": "favicon.ico"}
+--> {"result": [{"Title": "title", "SubTitle": "sub title", "IcoPath": "favicon.ico"}]}
  1. The API List is misleading because it is impossible for RPC Plugins to call many (all?) of those methods. For example, how is an RPC plugin supposed to call ChangeQuery or ShowMsg?

To Reproduce

No response

Screenshots

No response

Flow Launcher Version

1.19.2

Windows Build Number

22631.4169

Error Log

No response

@cspotcode cspotcode added the bug Something isn't working label Oct 12, 2024
@jjw24
Copy link
Member

jjw24 commented Oct 25, 2024

Documentation always needs work to keep up with changes. A PR is always more than welcome.

I will move this issue to the docs repo for visibility.

@jjw24 jjw24 transferred this issue from Flow-Launcher/Flow.Launcher Oct 25, 2024
@cspotcode
Copy link
Author

Thanks. However, I will need some guidance to understand the intended behavior.

Your answer suggests the current behavior is correct, and the docs are wrong. Should it be the other way around? I suspect that RPC plugins should be able to use Flow.Launcher's APIs, but somewhere along the line, that ability was lost during refactors.

As a start, can anyone help me understand the intent of each of the plugin-related classes?
What's the difference between V2 and V1?
Does Python get additional features that Node or Executable do not?

classDiagram
    IAsyncPlugin <|-- JsonRPCPluginBase
    JsonRPCPluginBase <|-- JsonRPCPluginV2
    JsonRPCPluginV2 <|-- ProcessStreamPluginV2
    ProcessStreamPluginV2 <|-- ExecutablePluginV2
    ProcessStreamPluginV2 <|-- NodePluginV2
    ProcessStreamPluginV2 <|-- PythonPluginV2
    JsonRPCPluginBase <|-- JsonRPCPlugin
    JsonRPCPlugin <|-- NodePlugin
    JsonRPCPlugin <|-- PythonPlugin
    JsonRPCPlugin <|-- ExecutablePlugin

    class IAsyncPlugin {
        <<interface>>
    }
Loading

@jjw24
Copy link
Member

jjw24 commented Oct 25, 2024

I haven't worked on the JsonRPC side of things for a long time, so my answer may not be accurate. To answer your question I also need to revisit the code and documentation myself.

As far as I know, JsonRPC V1 had limitations for non-C# plugins where they are unable to use API methods that take non-data types as parameters.

JsonRPC V2 (new implementation and not documented yet) allows these plugins to maintain constant communication as if they are native plugins.

@taooceros @Garulf are you able to help answer and explain @cspotcode's questions.

@cspotcode
Copy link
Author

Thank you. As a starting point, are plugin authors able to use V2 today? What is the communication channel between plugin and Flow? Is it newline-delimited JSON over stdin and stdout? Does it support concurrent method calls? For example, can a plugin write multiple calls to IFlowLauncher.FuzzySearch() to stdout and then wait for responses to all of them async? Must all calls be done serially, or must it wait for each return value before making the next call? Is each call paired with an ID allowing the return value to be associated to the call?

Any information about the protocol, or pointers to the relevant code, will be very helpful.

@cspotcode cspotcode changed the title BUG: JSON-RPC API docs denote backwards data flow; list API methods that are impossible to call JSON-RPC API: Understanding V1 vs V2, calling Flow APIs from plugins Oct 29, 2024
@taooceros
Copy link
Member

Yes it is usable, only not documented. It is newline-delimited JSON except for node plugin (as node plugin can use vscode jsonrpc so I made it compatible with it with the http header deliminater). A plugin should be able to write multiple calls to FuzzySearch async and wait for results all together async. Yes ID is used to associated.

The protocol is mainly just a JSONRPC 2.0 protocol.

@cspotcode
Copy link
Author

Thank you, how does a plugin use it today? If I specify "executable" in my plugin's plugin.json then I cannot use it, do I specify something else? Is the communication channel stdio or something else?

@cspotcode
Copy link
Author

except for node plugin (as node plugin can use vscode jsonrpc so I made it compatible with it with the http header deliminater).

I am writing executable plugins in Deno, a Node-compatible JavaScript runtime, so I should be able to use this library as well. The only difference is my plugins ship as a self-contained .exe to avoid dependencies. Is there a way to use vscode jsonrpc in my .exe plugin? Can I opt-in in my plugin.json?

@taooceros
Copy link
Member

taooceros commented Oct 29, 2024

Yeah that's a bit problematic. Currently it is hardcoded. I don't know whether I should make the http header delimitator the standard to do it? It might be annoying for plugin developed in other language to use.

Is there a reason you are using deno not node? I guess shipping a runtime can be quite large for a plugin.

@cspotcode
Copy link
Author

cspotcode commented Oct 29, 2024

Hmm, let me research the protocol. I wonder if it can be supported automatically by all plugins without requiring all plugins to understand it.

I'm using deno because the developer experience is simpler -- easier dependency management, automatic TypeScript support -- and I know I won't have to worry about node version incompatibilities. Shipping the runtime does make the plugins bigger, yes.

@cspotcode
Copy link
Author

I see what you mean about the http headers. If the plugin were initiating the connection, then Flow could detect whether or not the plugin sent a header, and respond accordingly. But since Flow sends the first message, that is impossible.

Maybe I am thinking about this wrong. If python, golang, rust plugins can all speak a JSONRPC protocol without headers, then surely I can find a JavaScript library to do the same. I don't need to use vscode-jsonrpc.

@taooceros
Copy link
Member

Sure. vscode json rpc might be the most sophisticated one (and it is also natively supported by the jsonrpc library we used in flow for interop). However, jsonrpc is a relatively simple protocol so I believe it is even possible to implement one by yourselves.

@cspotcode
Copy link
Author

Thank you. One question still remains:

Thank you, how does a plugin use [V2] today? If I specify "executable" in my plugin's plugin.json then I cannot use it, do I specify something else?

@taooceros
Copy link
Member

I think executable_v2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants