Stream: wit-bindgen

Topic: Instantiating resources on the guest


view this post on Zulip Alexander Lyon (Nov 12 2024 at 20:28):

Hey! I am working on a webassembly version of homeassistant at https://litehouse.arlyon.dev/docs. It is very much in its infancy but it's fun to hack on. My next goal is building a workflow engine to connect inputs (state conditions like 'switch pressed') to outputs (actions in the world like 'toggle light').

I am trying to figure out a good way to structure the plugins. The base plugin is implemented as a wit resource, and I am trying to find a decent pattern for modelling other interaction types (switch, notifier, media-player, etc). I would like the base plugin resource to be able to return a list of 'inputs' back to the host, which are other resources that it implements, such as 'turn switch on', 'turn switch off', 'play media'. Then the dynamic dispatch could be managed by the host rather than by the guest plugin.

Options:

I would like to do #1, are there any examples of this kind of thing in the wild I could look at? In the 1st case, is it even possible for the guest to instantiate other resources? I could return some data and have the host do it, but I can imagine a plugin author may want to share resources between a base plugin implementation and one of the resources it implements (or, in rust terms, have the same struct impl many traits). Are there facilities for doing this? Are there perhaps APIs to transmute a handle into another Resource type? In regards to versioning these interfaces, what happens if I link 0.1.0 of some wit and 0.2.0 at the same time? presumably it 'just works'?

Thanks for taking the time to read :)

Installing and using Litehouse

view this post on Zulip Alexander Lyon (Nov 12 2024 at 20:39):

interface plugin {
    // omitted

    variant output {
      switch(string),
      media(string),
      notify(string),
    }

    resource runner {
      constructor(nickname: string, config: option<string>);
      subscribe: func() -> result<list<subscription>, u32>;
      update: func(events: list<event>) -> result<bool, u32>;
      outputs: func() -> result<list<output>, u32>;
    }
}

interface media {
  // An additional interface for plugins that can play media
  resource media {
    constructor(nickname: string);
    play: func() -> result<bool, u32>;
    pause: func() -> result<bool, u32>;
    stop: func() -> result<bool, u32>;
    next: func() -> result<bool, u32>;
    previous: func() -> result<bool, u32>;
  }
}

interface switch {
  // An additional interface for plugins that can be turned on and off
  resource switch {
    constructor(nickname: string);
    on: func() -> result<bool, u32>;
    off: func() -> result<bool, u32>;
    toggle: func() -> result<bool, u32>;
  }
}

interface notify {
  // An additional interface for plugins that can notify the user
  resource notify {
    constructor(nickname: string);
    notify: func(message: string) -> result<bool, u32>;
  }
}

view this post on Zulip Lann Martin (Nov 12 2024 at 20:42):

Hey that's really neat! As a current user of home assistant I've thought about doing this sort of thing for a long time!

view this post on Zulip Lann Martin (Nov 12 2024 at 20:45):

perhaps these worlds could be pluggable themselves rather than bundled with the server.

Are you hoping for build-time plugins or runtime? I designed a system that does the former: Spin Factors. It's definitely a significant chunk of work but doable.

Spin is the open source developer tool for building and running serverless applications powered by WebAssembly. - fermyon/spin

view this post on Zulip Lann Martin (Nov 12 2024 at 20:46):

Runtime plugins are also possible but would require a much deeper understanding of the component model as you wouldn't be able to rely on bindings generation on the host (as it currently exists)

view this post on Zulip Alexander Lyon (Nov 12 2024 at 20:52):

Right now the server and plugin use the same WIT, and I am ok with keeping it that way for now. There are few enough people writing plugins (1 :joy:) that I can update all the plugins after a breaking change to the WIT. so for now, lets assume the server knows all the possible additional resources at build time

view this post on Zulip Alexander Lyon (Nov 12 2024 at 20:55):

Spin factors looks like it resolves the issue that the server needs to know of all the resources ahead of time so perhaps that is worth pursuing down the line!

view this post on Zulip Alexander Lyon (Nov 12 2024 at 20:58):

So I guess to restate the immediate issue, the guests should have some facility to expose to the host what subset of these available resources it is capable of. I was hoping to do that via instantiating resources inside the guest (returning types that implement traits) for the sake of plugin author ergonomics.

view this post on Zulip Ralph (Nov 22 2024 at 08:24):

Hey Alexander, this is a great project. If you stick to WIT, you'll undoubtedly end up with lots of implementations that interoperate. The "dynamic" part is in fact hard at the moment, of course. Pursuing Spin is one path, because it's oss and based on components......

view this post on Zulip Alexander Lyon (Dec 13 2024 at 12:23):

Sorry for reviving an old thread, but as hobby work goes haven't had time to look at this much. Spin factors looks cool. Am I right in saying that it wouldn't be possible to have the guest share data between multiple factors (worlds)? ie. the same struct on the guest implementing multiple factors at once which can share the same data


Last updated: Dec 23 2024 at 12:05 UTC