Files
LorenEteval_Furious/Furious/Plugins
2026-08-12 12:20:17 +08:00
..
2026-08-12 12:20:16 +08:00
2026-08-12 12:20:16 +08:00
2026-08-12 12:20:15 +08:00
2026-08-12 12:20:16 +08:00

Furious plugins

Furious core support is provided through FuriousPlugin implementations. The host GUI owns application lifecycle, storage, subscriptions, routing setup, and the tun2socks sidecar. A plugin owns everything specific to a proxy core:

  • configuration recognition, URI import/export, and blank configurations;
  • server protocols and their Add Server menu metadata;
  • configuration editor construction;
  • optional management actions and routing choices;
  • core process construction and startup;
  • download-test configuration adaptation;
  • optional environment setup and post-connection maintenance, such as core asset updates;
  • optional native TUN configuration, replacing the host's tun2socks sidecar;
  • plugin-specific process exit messages and version strings;
  • plugin-specific log timestamp highlighting.

The bundled implementations live under Furious.Plugins.Official. Core, configuration, and editor implementations are imported from their plugin packages; host packages intentionally expose only host-owned components.

Registered core plugins appear under Plugins > Core in the main window. Plugins may return actions from createManagementActions to populate their own submenu. Plugins without management actions remain visible as supported cores.

Third-party discovery

Third-party packages register an entry point in pyproject.toml:

[project.entry-points."furious.plugins"]
example-core = "furious_example.plugin:ExamplePlugin"

The entry point may expose a FuriousPlugin instance, a FuriousPlugin subclass, a zero-argument callable returning one plugin, or a list/tuple of plugins. Plugins execute inside the Furious process and must therefore be treated as trusted Python code.

from Furious.Plugins import FuriousPlugin, PluginProtocol, PluginRouting


class ExamplePlugin(FuriousPlugin):
    apiVersion = 1
    pluginId = 'example.core'
    displayName = 'Example Core'
    protocols = (
        PluginProtocol(
            id='example',
            displayName='Example',
            addActionText='Add Example Server...',
            menuOrder=100,
            separatorBefore=True,
        ),
    )
    configurationTypes = (ExampleConfig,)
    coreTypes = (ExampleCore,)

    # Implement configFromString/configFromDict, blankConfig,
    # createEditorForProtocol, startCore, and prepareDownloadTest as needed.
    # createManagementActions, routingOptions,
    # prepareTUN, configureEnvironment, afterConnected, and
    # logTimestampPatterns are optional.

routingOptions(config) may return PluginRouting values for routing modes supported by the given configuration. The tray Routing submenu follows the active server's plugin and is hidden when that plugin returns no routing modes. The host validates the current setting and falls back to the plugin's first option before starting its core. Routing display names are treated as literal text by default; set translatable=True only when the display name is an application translation key. User-provided labels should remain literal.

Configuration classes should subclass ConfigFactory and implement its table display, proxy endpoint, validity, serialization, and URI methods. Core process classes normally subclass CoreProcessWorker; editor dialogs normally subclass GuiEditorWidgetQDialog.

Plugin modules can be discovered while the Furious.Qt package is still being initialized. Keep metadata, configuration, routing, and core imports at module scope, but defer imports of Qt-dependent editors, windows, actions, and managers until their plugin hook is called.

prepareTUN(config) is called only for a normal connection while the host is in TUN mode. It may modify the copied runtime configuration and return True to indicate that the plugin handles TUN itself. Returning False keeps the host-provided tun2socks implementation.

Protocol IDs are case-insensitive. Plugin IDs, protocol IDs, configuration types, and core types must be unique. Conflicting or incompatible third-party plugins are rejected without preventing other entry points from loading.