ticket: add plugin authoring roadmap
This commit is contained in:
parent
c8877b49a4
commit
8b42e319e2
0
.yoi/tickets/00001KVHKWNQA/artifacts/.gitkeep
Normal file
0
.yoi/tickets/00001KVHKWNQA/artifacts/.gitkeep
Normal file
37
.yoi/tickets/00001KVHKWNQA/artifacts/relations.json
Normal file
37
.yoi/tickets/00001KVHKWNQA/artifacts/relations.json
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"relations": [
|
||||||
|
{
|
||||||
|
"ticket_id": "00001KVHKWNQA",
|
||||||
|
"kind": "depends_on",
|
||||||
|
"target": "00001KVG0HR96",
|
||||||
|
"note": "PDK targets the Component Model Tool runtime.",
|
||||||
|
"author": "yoi ticket",
|
||||||
|
"at": "2026-06-20T04:17:24Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ticket_id": "00001KVHKWNQA",
|
||||||
|
"kind": "related",
|
||||||
|
"target": "00001KVFD3YSV",
|
||||||
|
"note": "PDK authoring flow should pair with read-only plugin inspection.",
|
||||||
|
"author": "yoi ticket",
|
||||||
|
"at": "2026-06-20T04:17:24Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ticket_id": "00001KVHKWNQA",
|
||||||
|
"kind": "related",
|
||||||
|
"target": "00001KVFDX9AF",
|
||||||
|
"note": "PDK should later wrap https host API ergonomically.",
|
||||||
|
"author": "yoi ticket",
|
||||||
|
"at": "2026-06-20T04:17:24Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ticket_id": "00001KVHKWNQA",
|
||||||
|
"kind": "related",
|
||||||
|
"target": "00001KVFDX9AY",
|
||||||
|
"note": "PDK should later wrap fs host API ergonomically.",
|
||||||
|
"author": "yoi ticket",
|
||||||
|
"at": "2026-06-20T04:17:24Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
88
.yoi/tickets/00001KVHKWNQA/item.md
Normal file
88
.yoi/tickets/00001KVHKWNQA/item.md
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
---
|
||||||
|
title: 'Plugin: add Rust PDK and embedded authoring templates for Component Model Tools'
|
||||||
|
state: 'ready'
|
||||||
|
created_at: '2026-06-20T04:16:14Z'
|
||||||
|
updated_at: '2026-06-20T04:17:24Z'
|
||||||
|
assignee: null
|
||||||
|
readiness: 'implementation_ready'
|
||||||
|
risk_flags: ['plugin', 'pdk', 'component-model', 'authoring', 'templates', 'sdk', 'no-crates-io']
|
||||||
|
---
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
Yoi can now discover Plugin packages, register Tool surfaces, execute sandboxed WASM/Component Model Tool Plugins, enforce Plugin grants, expose `https` / `fs` host APIs, and inspect Plugin state through CLI. The next gap is authoring: independent Plugin developers should not need to write raw WIT/ABI glue or copy ad-hoc examples by hand.
|
||||||
|
|
||||||
|
This Ticket adds a first-party Rust PDK for Component Model Tool Plugins and embeds a starter template into Yoi resources. It deliberately does not publish to crates.io yet and does not fetch remote templates. The PDK/API and WIT world are still young, so out-of-tree authors should initially use a git rev or generated local path dependency rather than depending on a public semver crate.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Add a Rust PDK crate inside the Yoi workspace.
|
||||||
|
- Suggested package name: `yoi-plugin-pdk`.
|
||||||
|
- Suggested path: `crates/plugin-pdk`.
|
||||||
|
- Target Component Model Tool Plugins, not raw core-Wasm as the primary authoring path.
|
||||||
|
- PDK must be guest-side only.
|
||||||
|
- Do not depend on host runtime crates such as `pod`, `llm-worker`, `tui`, or `client`.
|
||||||
|
- Keep dependencies minimal, e.g. `serde`, `serde_json`, and WIT binding support.
|
||||||
|
- Do not expose ambient fs/network/env authority.
|
||||||
|
- Provide ergonomic Tool helpers.
|
||||||
|
- Typed JSON input parsing.
|
||||||
|
- Typed JSON output serialization.
|
||||||
|
- Structured `ToolError` / error-code helpers.
|
||||||
|
- `ToolContext` containing at least the tool name.
|
||||||
|
- Helper equivalent to `run_json_tool` that returns the ToolOutput JSON expected by the Yoi runtime.
|
||||||
|
- Provide Component Model binding glue.
|
||||||
|
- Re-export or wrap generated WIT bindings enough that an author does not need to hand-write raw pointer/length ABI code.
|
||||||
|
- Prefer a minimal `Guest` impl helper first; add a macro only if it is simpler and testable.
|
||||||
|
- Include embedded authoring templates under runtime resources.
|
||||||
|
- Suggested path: `resources/plugin/templates/rust-component-tool/`.
|
||||||
|
- Template includes `Cargo.toml`, `src/lib.rs`, `plugin.toml`, and a short README.
|
||||||
|
- Template should be usable by a future `yoi plugin new` command without network access.
|
||||||
|
- Template dependency policy:
|
||||||
|
- In checkout/dev mode, template may use a local path dependency to `crates/plugin-pdk`.
|
||||||
|
- For out-of-tree authors, docs/template comments should show a git `rev` dependency pattern.
|
||||||
|
- Do not publish or require crates.io for this Ticket.
|
||||||
|
- Do not use `curl | sh` or remote template fetch.
|
||||||
|
- Include at least one example or fixture Plugin using the PDK.
|
||||||
|
- Echo-style Component Model Tool is enough.
|
||||||
|
- It should compile to a component artifact through the documented toolchain or, if full component build automation is not yet available, be covered by a clear fixture/test boundary.
|
||||||
|
- Update Plugin development docs.
|
||||||
|
- Explain that Component Model + PDK is the preferred authoring path.
|
||||||
|
- Explain that raw core-Wasm ABI is compatibility/transitional.
|
||||||
|
- Explain why crates.io publication and remote templates are intentionally deferred.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- Workspace contains a guest-side `yoi-plugin-pdk` crate.
|
||||||
|
- A Rust Component Model Tool Plugin can use the PDK to implement a JSON Tool without raw pointer/length ABI code.
|
||||||
|
- PDK-produced Tool success output is accepted by the existing Yoi Plugin Tool runtime.
|
||||||
|
- PDK-produced Tool errors are bounded and represented as ordinary Tool result/error content.
|
||||||
|
- PDK does not grant or imply authority; host-side Plugin grants still decide `https` / `fs` / Tool execution access.
|
||||||
|
- Embedded `rust-component-tool` template exists in runtime resources and is suitable for future `yoi plugin new` expansion.
|
||||||
|
- No crates.io publication is required or performed.
|
||||||
|
- No remote template fetch is implemented.
|
||||||
|
- Tests cover:
|
||||||
|
- PDK JSON input/output happy path;
|
||||||
|
- PDK error output path;
|
||||||
|
- PDK sample/template compiles or fixture is validated;
|
||||||
|
- sample Plugin can be executed by Yoi component runtime if feasible in current test infrastructure;
|
||||||
|
- PDK has no host-runtime crate dependency.
|
||||||
|
- Validation: focused PDK/plugin tests, `cargo fmt --check`, relevant `cargo check` / `cargo test`, `git diff --check`, and `nix build .#yoi` because workspace/package/resources may change.
|
||||||
|
|
||||||
|
## Non-goals
|
||||||
|
|
||||||
|
- Publishing `yoi-plugin-pdk` to crates.io.
|
||||||
|
- Remote template fetch or `curl | sh` setup.
|
||||||
|
- `yoi plugin new/check/pack` CLI implementation.
|
||||||
|
- Multi-language PDKs.
|
||||||
|
- Service / Ingress authoring.
|
||||||
|
- WebSocket / inbound HTTP bridge support.
|
||||||
|
- Replacing Plugin grants with PDK-side checks.
|
||||||
|
|
||||||
|
## Related work
|
||||||
|
|
||||||
|
- `00001KVG0HR9M` — Objective: Plugin platform roadmap.
|
||||||
|
- `00001KVG0HR96` — Plugin Component Model runtime.
|
||||||
|
- `00001KVFD3YSV` — Plugin read-only CLI inspection.
|
||||||
|
- `00001KVFDX9AF` — Plugin https host API.
|
||||||
|
- `00001KVFDX9AY` — Plugin fs host API.
|
||||||
|
- `docs/development/plugin-development.md` — current Plugin development guide.
|
||||||
7
.yoi/tickets/00001KVHKWNQA/thread.md
Normal file
7
.yoi/tickets/00001KVHKWNQA/thread.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!-- event: create author: "yoi ticket" at: 2026-06-20T04:16:14Z -->
|
||||||
|
|
||||||
|
## 作成
|
||||||
|
|
||||||
|
LocalTicketBackend によって作成されました。
|
||||||
|
|
||||||
|
---
|
||||||
0
.yoi/tickets/00001KVHKWNQS/artifacts/.gitkeep
Normal file
0
.yoi/tickets/00001KVHKWNQS/artifacts/.gitkeep
Normal file
29
.yoi/tickets/00001KVHKWNQS/artifacts/relations.json
Normal file
29
.yoi/tickets/00001KVHKWNQS/artifacts/relations.json
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"relations": [
|
||||||
|
{
|
||||||
|
"ticket_id": "00001KVHKWNQS",
|
||||||
|
"kind": "depends_on",
|
||||||
|
"target": "00001KVHKWNQA",
|
||||||
|
"note": "Authoring new/check/pack uses the Rust PDK and embedded templates.",
|
||||||
|
"author": "yoi ticket",
|
||||||
|
"at": "2026-06-20T04:17:24Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ticket_id": "00001KVHKWNQS",
|
||||||
|
"kind": "related",
|
||||||
|
"target": "00001KVFD3YSV",
|
||||||
|
"note": "Authoring check/pack diagnostics should align with plugin list/show inspection.",
|
||||||
|
"author": "yoi ticket",
|
||||||
|
"at": "2026-06-20T04:17:24Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ticket_id": "00001KVHKWNQS",
|
||||||
|
"kind": "related",
|
||||||
|
"target": "00001KVG0HR96",
|
||||||
|
"note": "Authoring CLI validates Component Model Tool package metadata.",
|
||||||
|
"author": "yoi ticket",
|
||||||
|
"at": "2026-06-20T04:17:24Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
91
.yoi/tickets/00001KVHKWNQS/item.md
Normal file
91
.yoi/tickets/00001KVHKWNQS/item.md
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
---
|
||||||
|
title: 'Plugin: add authoring CLI new/check/pack'
|
||||||
|
state: 'ready'
|
||||||
|
created_at: '2026-06-20T04:16:14Z'
|
||||||
|
updated_at: '2026-06-20T04:17:24Z'
|
||||||
|
assignee: null
|
||||||
|
readiness: 'implementation_ready'
|
||||||
|
risk_flags: ['plugin', 'cli', 'authoring', 'templates', 'package-validation', 'packaging', 'read-only-check']
|
||||||
|
---
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
After the Rust PDK and embedded templates exist, independent Plugin developers need first-party CLI tooling to scaffold, validate, and package Plugins without relying on remote shell scripts or hand-written ZIP commands.
|
||||||
|
|
||||||
|
This Ticket adds authoring commands for local Plugin development. It complements read-only operational inspection (`yoi plugin list/show`) but serves a different audience: Plugin authors preparing a package before enabling it in Yoi.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Add Plugin authoring subcommands to the product CLI.
|
||||||
|
- `yoi plugin new rust-component-tool <path-or-name>`
|
||||||
|
- `yoi plugin check <path-or-package>`
|
||||||
|
- `yoi plugin pack <path> [--output <file>]`
|
||||||
|
- `new` uses embedded templates only.
|
||||||
|
- No remote template fetch.
|
||||||
|
- No `curl | sh` flow.
|
||||||
|
- Generated files should include `Cargo.toml`, `src/lib.rs`, `plugin.toml`, and README/next-steps.
|
||||||
|
- Generated dependency should be appropriate for the current checkout/release mode: local path in checkout mode, or documented git rev/tag pattern if out-of-tree.
|
||||||
|
- `check` validates a Plugin directory or `.yoi-plugin` package without executing Plugin code.
|
||||||
|
- Parse `plugin.toml`.
|
||||||
|
- Validate package id/version/source-compatible shape.
|
||||||
|
- Validate runtime kind and referenced artifact presence.
|
||||||
|
- Validate Component Model world metadata where possible.
|
||||||
|
- Validate Tool schema shape.
|
||||||
|
- Validate requested permissions / host API declarations.
|
||||||
|
- Validate archive safety for packages: path traversal, root escape, unsupported compression, bounded file count/size.
|
||||||
|
- Calculate and print deterministic digest.
|
||||||
|
- Produce actionable diagnostics and a suggested enablement/grant snippet.
|
||||||
|
- `pack` creates a deterministic `.yoi-plugin` package.
|
||||||
|
- Include required manifest/runtime files.
|
||||||
|
- Use currently supported archive format, including stored entries if compression is not supported.
|
||||||
|
- Reject unsafe paths / root escapes.
|
||||||
|
- Print output path and digest.
|
||||||
|
- Do not modify workspace enablement config.
|
||||||
|
- Provide JSON output for automation where useful.
|
||||||
|
- At minimum `check --json` and `pack --json`.
|
||||||
|
- Keep commands safe.
|
||||||
|
- `check` and `pack` do not execute Plugin code.
|
||||||
|
- `new` only writes into the requested destination and refuses to overwrite non-empty directories unless an explicit safe option is added.
|
||||||
|
- No secrets are generated or embedded.
|
||||||
|
- Integrate with existing inspection language.
|
||||||
|
- Diagnostics/statuses should align with `yoi plugin list/show` where possible.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- `yoi plugin new rust-component-tool ./my-plugin` creates a usable template without network access.
|
||||||
|
- `yoi plugin check ./my-plugin` validates the generated template and reports next steps/digest/enablement guidance.
|
||||||
|
- `yoi plugin pack ./my-plugin` creates a `.yoi-plugin` package that Yoi discovery can read.
|
||||||
|
- `check` can validate an existing `.yoi-plugin` archive.
|
||||||
|
- `check --json` returns a stable typed report suitable for tests/agents.
|
||||||
|
- `pack --json` returns output path and digest.
|
||||||
|
- Unsafe package paths / traversal / unsupported compression / missing manifest / missing runtime artifact are rejected with clear diagnostics.
|
||||||
|
- Commands do not execute Plugin code or mutate enablement config.
|
||||||
|
- Tests cover:
|
||||||
|
- `new` generated file set;
|
||||||
|
- refusal to overwrite non-empty destination;
|
||||||
|
- `check` valid directory;
|
||||||
|
- `check` invalid manifest;
|
||||||
|
- `check` missing runtime artifact;
|
||||||
|
- `check` unsafe package archive;
|
||||||
|
- `pack` deterministic digest;
|
||||||
|
- `pack` package is discoverable by existing Plugin discovery;
|
||||||
|
- JSON report shape.
|
||||||
|
- Validation: focused CLI/plugin authoring tests, relevant `cargo check` / `cargo test`, `cargo fmt --check`, `git diff --check`, and `nix build .#yoi` because product CLI/resources/packaging behavior changes.
|
||||||
|
|
||||||
|
## Non-goals
|
||||||
|
|
||||||
|
- Remote template fetching.
|
||||||
|
- Publishing or installing from a registry.
|
||||||
|
- Enabling/disabling Plugins in workspace config.
|
||||||
|
- Executing Plugin code during `check`.
|
||||||
|
- crates.io publication of PDK.
|
||||||
|
- Service / Ingress scaffolding.
|
||||||
|
- Multi-language templates beyond Rust Component Model Tool.
|
||||||
|
|
||||||
|
## Related work
|
||||||
|
|
||||||
|
- `00001KVG0HR9M` — Objective: Plugin platform roadmap.
|
||||||
|
- `00001KVHKWNQA` — Rust PDK and embedded authoring templates.
|
||||||
|
- `00001KVFD3YSV` — Plugin read-only CLI inspection list/show.
|
||||||
|
- `00001KVG0HR96` — Plugin Component Model runtime.
|
||||||
|
- `docs/development/plugin-development.md` — current Plugin development guide.
|
||||||
7
.yoi/tickets/00001KVHKWNQS/thread.md
Normal file
7
.yoi/tickets/00001KVHKWNQS/thread.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!-- event: create author: "yoi ticket" at: 2026-06-20T04:16:14Z -->
|
||||||
|
|
||||||
|
## 作成
|
||||||
|
|
||||||
|
LocalTicketBackend によって作成されました。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
@ -12,9 +12,10 @@ It is not a dumping ground for external research, old plans, API inventories, or
|
||||||
4. [`design/profiles-manifests-prompts.md`](design/profiles-manifests-prompts.md) — reusable Profiles, resolved Manifests, and prompt resources.
|
4. [`design/profiles-manifests-prompts.md`](design/profiles-manifests-prompts.md) — reusable Profiles, resolved Manifests, and prompt resources.
|
||||||
5. [`design/tool-permissions-scope.md`](design/tool-permissions-scope.md) — tool policy and filesystem scope.
|
5. [`design/tool-permissions-scope.md`](design/tool-permissions-scope.md) — tool policy and filesystem scope.
|
||||||
6. [`design/plugin-packages.md`](design/plugin-packages.md) — plugin package distribution, discovery, and enablement boundaries.
|
6. [`design/plugin-packages.md`](design/plugin-packages.md) — plugin package distribution, discovery, and enablement boundaries.
|
||||||
7. [`design/memory-knowledge.md`](design/memory-knowledge.md) — generated memory, Knowledge, and audit records.
|
7. [`development/plugin-development.md`](development/plugin-development.md) — how to build, package, enable, and inspect Yoi Plugins.
|
||||||
8. [`development/work-items.md`](development/work-items.md) — how project work is recorded and reviewed.
|
8. [`design/memory-knowledge.md`](design/memory-knowledge.md) — generated memory, Knowledge, and audit records.
|
||||||
9. [`development/validation.md`](development/validation.md) — how to check changes.
|
9. [`development/work-items.md`](development/work-items.md) — how project work is recorded and reviewed.
|
||||||
|
10. [`development/validation.md`](development/validation.md) — how to check changes.
|
||||||
|
|
||||||
## What belongs here
|
## What belongs here
|
||||||
|
|
||||||
|
|
|
||||||
274
docs/development/plugin-development.md
Normal file
274
docs/development/plugin-development.md
Normal file
|
|
@ -0,0 +1,274 @@
|
||||||
|
# Plugin development
|
||||||
|
|
||||||
|
This guide is for building a Yoi Plugin outside the Yoi runtime codebase. It describes the current Plugin package shape, how to author a Tool Plugin, how to enable it in a workspace, and how to inspect/debug it.
|
||||||
|
|
||||||
|
Yoi Plugins are intentionally explicit:
|
||||||
|
|
||||||
|
- putting a package in `.yoi/plugins` only makes it discoverable;
|
||||||
|
- a Profile/config entry must explicitly enable it;
|
||||||
|
- Plugin grants must allow its surfaces and host APIs;
|
||||||
|
- Plugin code runs only through the configured sandbox runtime;
|
||||||
|
- Tool calls and Tool results use the ordinary Yoi Tool/Worker history path.
|
||||||
|
|
||||||
|
## Current status
|
||||||
|
|
||||||
|
Implemented foundation:
|
||||||
|
|
||||||
|
- package discovery from project/user Plugin stores;
|
||||||
|
- explicit enablement resolution;
|
||||||
|
- Tool surface registration;
|
||||||
|
- Plugin permission grants;
|
||||||
|
- raw core-Wasm Tool runtime;
|
||||||
|
- Component Model Tool runtime;
|
||||||
|
- `https` and `fs` host APIs for Tool runtime;
|
||||||
|
- read-only `yoi plugin list/show` inspection.
|
||||||
|
|
||||||
|
Still intentionally separate/future work:
|
||||||
|
|
||||||
|
- `yoi plugin new/check/pack` authoring commands;
|
||||||
|
- polished multi-language SDK/PDK crates;
|
||||||
|
- Service / Ingress surfaces;
|
||||||
|
- WebSocket or inbound HTTP for bidirectional bridges;
|
||||||
|
- public registry/install/update/signature tooling.
|
||||||
|
|
||||||
|
## Package locations
|
||||||
|
|
||||||
|
Yoi discovers `.yoi-plugin` packages from:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<workspace>/.yoi/plugins/*.yoi-plugin
|
||||||
|
${XDG_DATA_HOME:-~/.local/share}/yoi/plugins/*.yoi-plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
Use project packages for workspace-specific Plugins and user packages for personal reusable Plugins. Project packages should normally be committed only when the package content is safe and intended to be part of the project.
|
||||||
|
|
||||||
|
## Package archive format
|
||||||
|
|
||||||
|
A `.yoi-plugin` package is currently a bounded ZIP archive. For now, create it with stored entries, not compressed entries:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
(cd my-plugin && zip -0 -r ../example.echo.yoi-plugin plugin.toml plugin.component.wasm)
|
||||||
|
```
|
||||||
|
|
||||||
|
The archive root must contain `plugin.toml`. Runtime files referenced by the manifest must also be inside the archive. Yoi rejects path traversal, root escapes, malformed manifests, unsupported API/runtime versions, and other unsafe archive shapes.
|
||||||
|
|
||||||
|
## Manifest: `plugin.toml`
|
||||||
|
|
||||||
|
A minimal Component Model Tool Plugin manifest looks like this:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
schema_version = 1
|
||||||
|
id = "example.echo"
|
||||||
|
name = "Example Echo"
|
||||||
|
version = "0.1.0"
|
||||||
|
surfaces = ["tool"]
|
||||||
|
permissions = [
|
||||||
|
{ kind = "surface", surface = "tool" },
|
||||||
|
{ kind = "tool", name = "example_echo" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[runtime]
|
||||||
|
kind = "wasm-component"
|
||||||
|
component = "plugin.component.wasm"
|
||||||
|
world = "yoi:plugin/tool@1.0.0"
|
||||||
|
|
||||||
|
[[tools]]
|
||||||
|
name = "example_echo"
|
||||||
|
description = "Echo input text."
|
||||||
|
input_schema = { type = "object", properties = { text = { type = "string" } }, required = ["text"], additionalProperties = false }
|
||||||
|
external_write = false
|
||||||
|
```
|
||||||
|
|
||||||
|
The preferred new runtime is `wasm-component`. The older raw core-Wasm runtime remains explicit for compatibility:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[runtime]
|
||||||
|
kind = "wasm"
|
||||||
|
entry = "plugin.wasm"
|
||||||
|
abi = "yoi-plugin-wasm-1"
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not rely on package presence to activate anything. Discovery only records inventory.
|
||||||
|
|
||||||
|
## Component Model authoring sketch
|
||||||
|
|
||||||
|
Yoi's Component Model Tool world is stored in `resources/plugin/wit/`. A minimal Rust sketch is available at:
|
||||||
|
|
||||||
|
```text
|
||||||
|
docs/examples/plugin-component-tool/lib.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
The important authoring shape is:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
wit_bindgen::generate!({
|
||||||
|
world: "tool",
|
||||||
|
path: "../../../resources/plugin/wit",
|
||||||
|
});
|
||||||
|
|
||||||
|
struct Plugin;
|
||||||
|
|
||||||
|
impl Guest for Plugin {
|
||||||
|
fn call(tool_name: String, input_json: String) -> String {
|
||||||
|
format!(
|
||||||
|
r#"{{"summary":"component tool {tool_name}","content":"input was {input_json}"}}"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export!(Plugin);
|
||||||
|
```
|
||||||
|
|
||||||
|
The returned string is ordinary `ToolOutput` JSON. It is routed through the normal Tool result path; the component cannot inject hidden context.
|
||||||
|
|
||||||
|
The exact build pipeline depends on the authoring toolchain (`wit-bindgen`, component adapter tooling, etc.). Until `yoi plugin new/check/pack` exists, Plugin authors should treat the example as the ABI contract sketch and use `yoi plugin list/show` plus focused runtime tests to verify packages.
|
||||||
|
|
||||||
|
## Enabling a Plugin in a workspace
|
||||||
|
|
||||||
|
Enablement belongs in the resolved Profile/config path for the workspace. For local dogfooding or private experiments, use the ignored local overlay rather than committing secrets or local paths:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# .yoi/override.local.toml
|
||||||
|
|
||||||
|
[features]
|
||||||
|
plugins = true
|
||||||
|
|
||||||
|
[[plugins.enabled]]
|
||||||
|
id = "project:example.echo"
|
||||||
|
version = "0.1.0"
|
||||||
|
digest = "sha256:<digest from yoi plugin show/list>"
|
||||||
|
surfaces = ["tool"]
|
||||||
|
|
||||||
|
[plugins.enabled.grants]
|
||||||
|
id = "project:example.echo"
|
||||||
|
version = "0.1.0"
|
||||||
|
digest = "sha256:<same digest>"
|
||||||
|
permissions = [
|
||||||
|
{ kind = "surface", surface = "tool" },
|
||||||
|
{ kind = "tool", name = "example_echo" },
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
A source-qualified id is preferred:
|
||||||
|
|
||||||
|
```text
|
||||||
|
project:example.echo
|
||||||
|
user:example.echo
|
||||||
|
builtin:example.echo
|
||||||
|
```
|
||||||
|
|
||||||
|
Unqualified ids can be ambiguous and should fail closed when more than one source matches.
|
||||||
|
|
||||||
|
## Inspecting Plugins
|
||||||
|
|
||||||
|
Use the read-only CLI inspection commands first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yoi plugin list
|
||||||
|
yoi plugin list --json
|
||||||
|
yoi plugin show project:example.echo
|
||||||
|
yoi plugin show project:example.echo --json
|
||||||
|
```
|
||||||
|
|
||||||
|
`list/show` must not execute Plugin code. They are intended to explain static state:
|
||||||
|
|
||||||
|
- discovered packages;
|
||||||
|
- enabled vs disabled packages;
|
||||||
|
- missing packages referenced by enablement;
|
||||||
|
- invalid manifests;
|
||||||
|
- digest/version/source mismatches;
|
||||||
|
- granted/denied permissions;
|
||||||
|
- Tool registration eligibility;
|
||||||
|
- runtime metadata.
|
||||||
|
|
||||||
|
Typical statuses:
|
||||||
|
|
||||||
|
```text
|
||||||
|
active enabled and statically valid for at least one surface/tool
|
||||||
|
disabled discovered but not explicitly enabled
|
||||||
|
missing enablement references a package that is not discovered
|
||||||
|
rejected invalid manifest, incompatible API, digest mismatch, grant denial, etc.
|
||||||
|
partial usable package with some rejected surfaces/tools
|
||||||
|
```
|
||||||
|
|
||||||
|
## `https` host API
|
||||||
|
|
||||||
|
The `https` host API is outbound-only and grant-gated. It is meant for Tool calls such as webhook posting or REST requests. It is not a WebSocket/Gateway or inbound HTTP bridge.
|
||||||
|
|
||||||
|
Manifest permissions should request `host_api.https` in addition to the Tool permissions. Enablement grants must then allow the API and constrain hosts/methods.
|
||||||
|
|
||||||
|
Example grant shape:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[plugins.enabled.grants]
|
||||||
|
permissions = [
|
||||||
|
{ kind = "surface", surface = "tool" },
|
||||||
|
{ kind = "tool", name = "discord_post" },
|
||||||
|
{ kind = "host_api", api = "https" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[plugins.enabled.grants.https]]
|
||||||
|
host = "discord.com"
|
||||||
|
methods = ["POST"]
|
||||||
|
path_prefixes = ["/api/webhooks/"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Yoi rejects `http://`, localhost/private/link-local targets, disallowed hosts/methods, oversize requests/responses, and missing grants. Credentials must come from explicit config/secret references, not ambient environment variables.
|
||||||
|
|
||||||
|
## `fs` host API
|
||||||
|
|
||||||
|
The `fs` host API is Plugin-scoped and grant-gated. Plugins do not inherit the Pod/workspace filesystem authority automatically.
|
||||||
|
|
||||||
|
Example grant shape:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[plugins.enabled.grants]
|
||||||
|
permissions = [
|
||||||
|
{ kind = "surface", surface = "tool" },
|
||||||
|
{ kind = "tool", name = "read_notes" },
|
||||||
|
{ kind = "host_api", api = "fs" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[plugins.enabled.grants.fs]]
|
||||||
|
root = "/absolute/path/to/plugin-data"
|
||||||
|
operations = ["read", "list"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Yoi normalizes paths, rejects `..` traversal, rejects symlink/root escapes, and applies read/write/list bounds. Diagnostics must not include file contents.
|
||||||
|
|
||||||
|
## Outbound vs bridge integrations
|
||||||
|
|
||||||
|
After `https`, an outbound Discord webhook Tool is feasible:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Yoi Tool call -> Plugin Tool -> yoi:host/https -> Discord REST/webhook
|
||||||
|
```
|
||||||
|
|
||||||
|
A bidirectional Discord bridge is different. It needs a Service surface plus Ingress and either WebSocket/Gateway support or inbound HTTP interactions:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Discord Gateway/Webhook -> Plugin Service/Ingress -> host routing policy -> notify/run/drop/diagnostic
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not model bidirectional bridge work as an `https` Tool alone.
|
||||||
|
|
||||||
|
## Development checklist
|
||||||
|
|
||||||
|
1. Create a package directory with `plugin.toml` and the runtime artifact.
|
||||||
|
2. Build the Wasm/component artifact.
|
||||||
|
3. Package with stored ZIP entries as `.yoi-plugin`.
|
||||||
|
4. Put it under `.yoi/plugins/` or the user Plugin store.
|
||||||
|
5. Run `yoi plugin list` and `yoi plugin show <ref>`.
|
||||||
|
6. Add explicit enablement and grants.
|
||||||
|
7. Re-run `yoi plugin show <ref>` until status/diagnostics are correct.
|
||||||
|
8. Start Yoi with `features.plugins = true` in the resolved config/Profile.
|
||||||
|
9. Call the Tool and verify ordinary Tool result/history behavior.
|
||||||
|
|
||||||
|
## Safety rules for Plugin authors
|
||||||
|
|
||||||
|
- Do not assume ambient filesystem, network, or environment access.
|
||||||
|
- Do not put secrets in `plugin.toml` or package files.
|
||||||
|
- Request only the minimal host APIs and grants needed.
|
||||||
|
- Keep Tool output bounded and structured.
|
||||||
|
- Prefer Component Model authoring for new Plugins.
|
||||||
|
- Treat raw core-Wasm ABI support as transitional compatibility.
|
||||||
Loading…
Reference in New Issue
Block a user