diff --git a/build-an-oracle/develop/enable-bundled-plugins.mdx b/build-an-oracle/develop/enable-bundled-plugins.mdx index 3879966..1f20db7 100644 --- a/build-an-oracle/develop/enable-bundled-plugins.mdx +++ b/build-an-oracle/develop/enable-bundled-plugins.mdx @@ -1,6 +1,6 @@ --- title: "Enable bundled plugins" -description: "Toggle the 15 bundled QiForge plugins via the features map — opt out, force on, or let auto-detect handle it — and retune their manifests." +description: "Toggle the 16 bundled QiForge plugins via the features map — opt out, force on, or let auto-detect handle it — and retune their manifests." icon: "boxes-stacked" --- @@ -31,7 +31,7 @@ That's the whole surface. The runtime pre-loads every bundled plugin instance fr - [`BUNDLED_PLUGINS`](https://github.com/ixoworld/ixo-oracles-boilerplate/blob/main/packages/oracle-runtime/src/plugins/index.ts) is a fixed 15-plugin tuple — memory, portal, firecrawl, domain-indexer, composio, sandbox, skills, editor, agui, slack, tasks, credits, calls, user-preferences, matrix-group-chats. + [`BUNDLED_PLUGINS`](https://github.com/ixoworld/ixo-oracles-boilerplate/blob/main/packages/oracle-runtime/src/plugins/index.ts) is a fixed 16-plugin tuple — memory, portal, firecrawl, domain-indexer, composio, sandbox, skills, editor, agui, slack, tasks, credits, calls, user-preferences, matrix-group-chats, vfs. You do not import or instantiate the plugins you want at defaults — they are already there. @@ -82,6 +82,7 @@ Each plugin's `autoDetect` predicate decides whether to opt in when you leave it | `calls` | always on | Visibility `silent`; placeholder stub (no tools yet) | | `user-preferences` | always on | Visibility `always` | | `matrix-group-chats` | always on | Visibility `on-demand`; gating middleware + tools fire only in Matrix group rooms (`memberCount > 2`) | +| `vfs` | always on | Visibility `always`; worker URLs derived from `NETWORK`. Contributes tools only when the oracle has a UCAN signing key and the user granted filesystem access | Full per-plugin env vars: [plugin catalog](/build-an-oracle/reference/bundled-plugins/overview) and [environment variables reference](/build-an-oracle/reference/environment-variables). diff --git a/build-an-oracle/for-ai-agents.mdx b/build-an-oracle/for-ai-agents.mdx index 4cd7c0a..fba9837 100644 --- a/build-an-oracle/for-ai-agents.mdx +++ b/build-an-oracle/for-ai-agents.mdx @@ -14,7 +14,7 @@ If you are an AI agent: read top-to-bottom once. Every signature you need is inl ## TL;DR — what you produce -A QiForge oracle is **one `main.ts`** that calls `createOracleApp({ config, plugins, … })` plus **one folder per plugin** under `src/plugins//`. The runtime handles HTTP, auth, the agent graph, the checkpointer, Matrix, and bundles 15 plugins by default. You ship glue code, not infrastructure. +A QiForge oracle is **one `main.ts`** that calls `createOracleApp({ config, plugins, … })` plus **one folder per plugin** under `src/plugins//`. The runtime handles HTTP, auth, the agent graph, the checkpointer, Matrix, and bundles 16 plugins by default. You ship glue code, not infrastructure. ## main.ts shape diff --git a/build-an-oracle/index.mdx b/build-an-oracle/index.mdx index 8852b74..22a5a48 100644 --- a/build-an-oracle/index.mdx +++ b/build-an-oracle/index.mdx @@ -38,7 +38,7 @@ That's a working oracle. One call to [`createOracleApp`](/build-an-oracle/develo Per-request agent build, dynamic tool loading via meta-tools, four always-on middleware (capability gating, tool validation, repetition guard, retry). - + `memory`, `skills`, `sandbox`, `portal`, `firecrawl`, `composio`, `editor`, `agui`, `slack`, `credits`, `user-preferences`, and more — toggle them via the `features` map. diff --git a/build-an-oracle/quickstart.mdx b/build-an-oracle/quickstart.mdx index 897158a..d943a88 100644 --- a/build-an-oracle/quickstart.mdx +++ b/build-an-oracle/quickstart.mdx @@ -14,7 +14,7 @@ Oracle: (calls list_capabilities → load_capability(weather) → get_current_we A live oracle on `localhost:3000` with: -- The 15 bundled plugins resolved at boot. +- The 16 bundled plugins resolved at boot. - A custom Weather plugin loading on demand. - A `GET /weather/now?city=X` public HTTP route. - A streaming chat endpoint over SSE. @@ -202,7 +202,7 @@ Watch the server logs at the same time — you'll see the weather middleware pri Every option you can pass — config, plugins, features, hooks. - The 15 plugins shipped with the runtime. + The 16 plugins shipped with the runtime. Dense one-pager with every signature inlined. diff --git a/build-an-oracle/reference/bundled-plugins/overview.mdx b/build-an-oracle/reference/bundled-plugins/overview.mdx index 2cea292..33f1a3d 100644 --- a/build-an-oracle/reference/bundled-plugins/overview.mdx +++ b/build-an-oracle/reference/bundled-plugins/overview.mdx @@ -4,7 +4,7 @@ description: "Reference for every plugin the oracle runtime ships with — toggl icon: "boxes-stacked" --- -The runtime bundles 15 plugins that load by default; opt out per plugin via the `features` map on `createOracleApp`. One additional plugin — [`flows`](/build-an-oracle/reference/bundled-plugins/flows) — ships in the package but is **opt-in only**: wire it in explicitly via the `plugins` array. +The runtime bundles 16 plugins that load by default; opt out per plugin via the `features` map on `createOracleApp`. One additional plugin — [`flows`](/build-an-oracle/reference/bundled-plugins/flows) — ships in the package but is **opt-in only**: wire it in explicitly via the `plugins` array. ## At a glance @@ -25,6 +25,7 @@ The runtime bundles 15 plugins that load by default; opt out per plugin via the | [`calls`](/build-an-oracle/reference/bundled-plugins/calls) | `silent` | On (stub) | — | — | | [`user-preferences`](/build-an-oracle/reference/bundled-plugins/user-preferences) | `always` | On | — | — | | [`matrix-group-chats`](/build-an-oracle/reference/bundled-plugins/matrix-group-chats) | `on-demand` | On | — | — | +| [`vfs`](/build-an-oracle/reference/bundled-plugins/vfs) | `always` | On | — (URLs from `NETWORK`) | — | | [`flows`](/build-an-oracle/reference/bundled-plugins/flows) | `on-demand` | Opt-in (not bundled) | — | `editor` Qi Flow engine | `Default state` legend: @@ -96,6 +97,9 @@ const app = await createOracleApp({ Gate the bot + per-room compacted memory for Matrix group rooms. + + Read, write, search, and share the user's real files on their Virtual Filesystem. + Author and inspect multi-step Qi Flow templates (opt-in). diff --git a/build-an-oracle/reference/bundled-plugins/vfs.mdx b/build-an-oracle/reference/bundled-plugins/vfs.mdx new file mode 100644 index 0000000..6c58392 --- /dev/null +++ b/build-an-oracle/reference/bundled-plugins/vfs.mdx @@ -0,0 +1,124 @@ +--- +title: "vfs" +description: "The user's Virtual Filesystem — read, create, edit, search, organise, and share their real files, inside the folder they granted the oracle." +icon: "folder" +--- + +**Source:** [`packages/oracle-runtime/src/plugins/vfs/`](https://github.com/ixoworld/ixo-oracles-boilerplate/blob/main/packages/oracle-runtime/src/plugins/vfs/) + +| Attribute | Value | +| --- | --- | +| Visibility | `always` | +| Stability | `stable` | +| Category | `data` | +| Default state | On (always-on; contributes tools only when the oracle has a UCAN signing key **and** the user has granted access) | +| Depends on | — (`sandbox` is an optional sibling — see [bridge tools](#sandbox-bridge-tools)) | + +## Summary + +The user's **Virtual Filesystem (VFS)** — their persistent, access-controlled home for real documents, notes, datasets, and artifacts, in folders, searchable and versioned. This is reusable context that lives across sessions — not sandbox scratch files, not chat attachments, not the web. + +The oracle acts **as the user**, inside the exact folder the user delegated to it. The **user owns their filesystem and is the sole grantor**: only their key can sign the delegation — the oracle can never grant itself access. Every file the oracle reads or writes is confined to the granted subtree and audited as `invoker=oracle, actor=user`. + +The filesystem is securely stored with managed encryption; authorized IXO services can read content to power search and previews, so it is **not** end-to-end encrypted — never describe it as zero-knowledge. + +## How the oracle gets access + +The user grants access from the IXO Portal — the oracle never self-grants: + + + + In the Portal: **your domain → Library → Files → Access** (top-right). + + + In **Manage access**, paste the oracle's account DID (its `ORACLE_DID`) as the Recipient DID, choose the rights (Read / Write / Delete), set the folder scope and duration, and **Grant access**. + + + The grant is a UCAN delegation deposited in the UCAN Store Worker, addressed to the oracle. Per request the oracle pulls that delegation and mints a fresh, single-use VFS invocation — no extra wiring. Until a grant exists, the file tools return a short message telling the user how to grant access (including the oracle's DID). + + + +See [Identity and auth](/build-an-oracle/develop/identity-and-auth) for the two-hop UCAN flow (oracle → UCAN Store → VFS). + +## Environment variables + +The worker URLs are **bundled per network** — there is nothing to configure. Everything else is optional tuning. + +| Var | Required | Description | +| --- | --- | --- | +| `NETWORK` | yes | `mainnet` / `testnet` / `devnet`. Selects the bundled VFS + UCAN Store worker URLs (`https://[testnet.\|devnet.]vfs.ixo.earth`). Owned by the core base env schema. | +| `VFS_MAX_READ_LINES` | no | Max lines a single `vfs_read` window returns. Default `2000`. | +| `VFS_REQUEST_TIMEOUT_MS` | no | Per-request timeout to the VFS worker. Default `20000`. | +| `SANDBOX_MCP_URL` | no | Read but not owned (declared by [`sandbox`](/build-an-oracle/reference/bundled-plugins/sandbox)). When set, adds the two [sandbox bridge tools](#sandbox-bridge-tools). | + +The oracle's UCAN signing key (loaded from its Matrix account room at boot) is required — without it the plugin contributes no tools. + +## What it contributes + +- **Tools:** ten file tools, each resolving a fresh single-use UCAN bearer per call: + + | Tool | Ability | What it does | + | --- | --- | --- | + | `vfs_search` | `fs/read` | Find files by meaning (hybrid lexical + semantic); returns paths + cited line ranges. | + | `vfs_grep` | `fs/read` | Find files containing an exact term. | + | `vfs_glob` | `fs/list` | Match files by path pattern, e.g. `/notes/*.md`, `**/*.pdf`. | + | `vfs_list` | `fs/list` | List a folder's contents. | + | `vfs_read` | `fs/read` | Read a file. Text → windowed numbered lines (page with `offset`); images/PDFs → transcribed via the vision model. | + | `vfs_write` | `fs/write` | Create a file (or overwrite when the user asked to replace it). | + | `vfs_edit` | `fs/write` | Exact-string edit — change one occurrence (or `replaceAll`). | + | `vfs_move` | `fs/write` | Move or rename a file. | + | `vfs_delete` | `fs/delete` | Move a file to trash (recoverable). | + | `vfs_share` | `fs/write` | Publish a file/folder and return an anyone-with-the-link URL. | + +- **Sub-agents:** none. +- **Middleware:** none. +- **HTTP routes:** none. +- **Shared state:** none. + +### Sandbox bridge tools + +When [`sandbox`](/build-an-oracle/reference/bundled-plugins/sandbox) is configured (`SANDBOX_MCP_URL` set), two extra tools move a file between the user's sandbox and their filesystem **server-side — the bytes never pass through the LLM**: + +- `sandbox_to_vfs` — persist something the sandbox produced (a report, export, chart) into the user's files so it survives the session. +- `vfs_to_sandbox` — feed one of the user's files into the sandbox (under `/workspace/data/`) so `sandbox_run` code can process it. + +## Opt out / Opt in + +```ts +const app = await createOracleApp({ + config, + features: { vfs: false }, // never load + // features: { vfs: true }, // force on (the default — always bundled) +}); +``` + +## When to use it + +- The user refers to a document, note, file, or folder they "saved", "uploaded", or "shared with you". +- You need to create, update, or organise a file that should persist across sessions. +- You need to find or quote something from the user's files ("what did my notes say about X"). +- You can reuse a file the user already has instead of asking them to re-paste it. +- The user asks you to share a file or make it downloadable. +- Persist a sandbox artifact into the user's files (`sandbox_to_vfs`), or feed a file into the sandbox (`vfs_to_sandbox`). + +## When NOT to use it + +- General knowledge or web questions — the files are the user's private content, not a knowledge base of the world. +- Content the user pasted directly into chat — act on it inline; don't write it to a file unless asked. +- Temporary/scratch files from a compute run — those belong to the [`sandbox`](/build-an-oracle/reference/bundled-plugins/sandbox), not the user's filesystem. +- Data another plugin owns (flows, skills, memory) — use that plugin. + + +If a file action reports no access (or read-only), the oracle relays the grant steps above — with its agent DID — so the user can authorize it, then retries. It never claims a file is missing when the real issue is access. + + +## Where to read next + + + + The two-hop UCAN flow that lets the oracle act as the user. + + + The compute box the VFS bridges to. + + diff --git a/build-an-oracle/reference/environment-variables.mdx b/build-an-oracle/reference/environment-variables.mdx index b3ed7cf..1ba9aa2 100644 --- a/build-an-oracle/reference/environment-variables.mdx +++ b/build-an-oracle/reference/environment-variables.mdx @@ -121,6 +121,8 @@ Only required when the named plugin is loaded. | `matrix-group-chats` | `GROUP_CHAT_ACTIVE_THREAD_TTL_MS` | No | Coerced int, min `60000`; default `1800000`. How long a thread stays "active with the bot" after a reply. | | `matrix-group-chats` | `GROUP_CHAT_REQUIRE_POWER_LEVEL` | No | Coerced int, min `0`; default `0`. Extra minimum power level the bot must have before posting (`0` = use the room default). | | `matrix-group-chats` | `GROUP_CHAT_ROOM_INFO_TTL_MS` | No | Coerced int, min `60000`; default `1800000`. How long roomInfo (membership, DM flag) stays cached. | +| `vfs` | `VFS_MAX_READ_LINES` | No | Coerced positive int; default `2000`. Max lines a single `vfs_read` window returns. | +| `vfs` | `VFS_REQUEST_TIMEOUT_MS` | No | Coerced positive int; default `20000`. Per-request timeout to the VFS worker. | ## Variables read but not owned @@ -129,6 +131,7 @@ Some plugins read variables that live in another schema: - **`composio`** reads the core `NETWORK` and forwards it as `x-ixo-network`. - **`skills`** reads `NETWORK` and forwards as `X-IXO-Network`. - **`sandbox`** reads `ORACLE_SECRETS` (core) and `SKILLS_CAPSULES_BASE_URL` (owned by `skills`) and forwards them as headers. +- **`vfs`** reads the core `NETWORK` (selects the bundled VFS + UCAN Store worker URLs — nothing to configure) and `SANDBOX_MCP_URL` (owned by `sandbox`; when set, adds the two sandbox↔files bridge tools). These are declared in the plugin's sibling schemas (typed `optional()`); a missing value just skips the matching header instead of failing the plugin build. diff --git a/build-an-oracle/reference/plugin-api.mdx b/build-an-oracle/reference/plugin-api.mdx index 61931b8..7d6f352 100644 --- a/build-an-oracle/reference/plugin-api.mdx +++ b/build-an-oracle/reference/plugin-api.mdx @@ -210,4 +210,4 @@ Boot-time errors in `autoDetect`, `configSchema` validation, or `manifest` valid - [PluginContext](/build-an-oracle/reference/plugin-context) - [RuntimeContext](/build-an-oracle/reference/runtime-context) - [Manifest schema](/build-an-oracle/reference/manifest-schema) -- [Plugin catalog](/build-an-oracle/reference/bundled-plugins/overview) — the 15 bundled plugins. +- [Plugin catalog](/build-an-oracle/reference/bundled-plugins/overview) — the 16 bundled plugins. diff --git a/build-an-oracle/understand/architecture.mdx b/build-an-oracle/understand/architecture.mdx index a93b8e7..f4b7a36 100644 --- a/build-an-oracle/understand/architecture.mdx +++ b/build-an-oracle/understand/architecture.mdx @@ -18,7 +18,7 @@ graph TB subgraph Runtime["@ixo/oracle-runtime"] Core["Always-on Nest modules
Sessions · Messages · WS · Secrets · UCAN · Auth · Subscription · Throttler · Checkpointer"] - Bundled["15 bundled plugins
memory · skills · sandbox · editor · agui · portal · firecrawl · domain-indexer · composio · slack · credits · user-preferences · matrix-group-chats · tasks · calls"] + Bundled["16 bundled plugins
memory · skills · sandbox · editor · agui · portal · firecrawl · domain-indexer · composio · slack · credits · user-preferences · matrix-group-chats · tasks · calls · vfs"] Agent["LangChain agent
built per request"] end @@ -51,7 +51,7 @@ You never edit this layer. Updates come via `pnpm update @ixo/oracle-runtime`. ### Layer 3 — Bundled plugins -15 plugins shipped inside the runtime package, each independently toggleable via `features`. See the [Plugin catalog](/build-an-oracle/reference/bundled-plugins/overview) for what each one does. +16 plugins shipped inside the runtime package, each independently toggleable via `features`. See the [Plugin catalog](/build-an-oracle/reference/bundled-plugins/overview) for what each one does. ## Bootstrap, in one picture diff --git a/build-an-oracle/understand/plugins-vs-skills.mdx b/build-an-oracle/understand/plugins-vs-skills.mdx index e972f1e..d6bc4c0 100644 --- a/build-an-oracle/understand/plugins-vs-skills.mdx +++ b/build-an-oracle/understand/plugins-vs-skills.mdx @@ -74,7 +74,7 @@ Not directly. Skills run in a sandbox; they don't see plugins or Nest DI. They g The recipe.
- The 15 bundled plugins — including `skills` and `sandbox`. + The 16 bundled plugins — including `skills` and `sandbox`. diff --git a/build-an-oracle/understand/what-is-qiforge.mdx b/build-an-oracle/understand/what-is-qiforge.mdx index bca85e8..81413ec 100644 --- a/build-an-oracle/understand/what-is-qiforge.mdx +++ b/build-an-oracle/understand/what-is-qiforge.mdx @@ -8,7 +8,7 @@ icon: "compass" An **Agentic Oracle** is an AI agent that owns a verifiable identity on IXO, talks to users through encrypted per-user Matrix rooms, authenticates every request via UCAN delegation, and composes its capabilities from plugins (compiled in) and skills (discovered at runtime). -**QiForge is the framework that lets you ship one.** The runtime (`@ixo/oracle-runtime`) handles bootstrap, auth, the agent loop, the checkpointer, Matrix wiring, and 15 bundled plugins. Your oracle is a thin `main.ts` plus whatever custom plugins you write. +**QiForge is the framework that lets you ship one.** The runtime (`@ixo/oracle-runtime`) handles bootstrap, auth, the agent loop, the checkpointer, Matrix wiring, and 16 bundled plugins. Your oracle is a thin `main.ts` plus whatever custom plugins you write. ## Three layers, one diagram diff --git a/docs.json b/docs.json index 7e72b01..80d9c2d 100644 --- a/docs.json +++ b/docs.json @@ -225,6 +225,7 @@ "build-an-oracle/reference/bundled-plugins/calls", "build-an-oracle/reference/bundled-plugins/user-preferences", "build-an-oracle/reference/bundled-plugins/matrix-group-chats", + "build-an-oracle/reference/bundled-plugins/vfs", "build-an-oracle/reference/bundled-plugins/flows" ] }