Context: AI, network, storage, settings
context.ai (requires ai)
Section titled “context.ai (requires ai)”interface AICompleteOptions { maxTokens?: number; systemPrompt?: string;}interface AIModel { id: string; name: string; }
complete(prompt: string, opts?: AICompleteOptions): Promise<string>;stream(prompt: string, opts: AICompleteOptions, onToken: (token: string) => void): Promise<void>;listModels(): Promise<AIModel[]>;complete/stream/listModels all use the user’s own configured AI
provider, model, and API key (whatever is set in Settings → AI) — a plugin
cannot supply its own key or provider. See
Trust model & security for what privacy mode does
and does not gate here.
context.network (requires network)
Section titled “context.network (requires network)”interface PluginFetchInit { body?: string; headers?: Record<string, string>; method?: string;}interface PluginFetchResponse { body: string; headers: Record<string, string>; status: number;}
fetch(url: string, init?: PluginFetchInit): Promise<PluginFetchResponse>;This is a Rust-side reqwest proxy (it bypasses the browser’s CORS
restrictions), not the browser fetch. Only http/https URLs are
allowed; the response body is always a UTF-8 string (binary responses are
lossily decoded, not usable as bytes); duplicate response headers collapse
to whichever value reqwest iterates last. See
Trust model & security for the full egress and
size/timeout policy.
context.storage (requires storage)
Section titled “context.storage (requires storage)”read(key: string): Promise<string | null>;write(key: string, value: string): Promise<void>;list(): Promise<string[]>;remove(key: string): Promise<void>;A simple string key/value store, one directory per plugin. See Trust model & security for where it lives and its guarantees (or lack thereof).
context.settings (requires settings)
Section titled “context.settings (requires settings)”getAll(): Record<string, boolean | number | string>;The user’s answers to the fields your manifest declares in
contributions.settings, rendered as a form in your plugin’s page under
Settings → Plugins. One entry per declared field, always of the declared
type; keys your current manifest does not declare are not returned.
Synchronous here and Promise-returning in the sandboxed tier — otherwise the
same function, resolved the same way, so the same plugin source works in both.
There is no setter in either tier: a value the user chose is not the plugin’s to
move. Use context.storage for state of your own.
const { prefix = "»" } = context.settings.getAll();Being told when a value changes
Section titled “Being told when a value changes”context.events.on("settings:changed", () => { rebuild(context.settings.getAll()); // the event carries no values});This one event is gated on settings, not on events, in both tiers — it carries no
payload, and requiring events would make your install dialog claim you watch what the
user does to their files. It is debounced, so a string field being typed into notifies you
once the value settles rather than once per keystroke.
‼️ The settings object a tiptapExtensions factory receives is a snapshot taken when
the plugin loads. The factory is not re-run, so read context.settings.getAll() when you
need a current value.
What a field may declare
Section titled “What a field may declare”interface PluginSettingField { key: string; label: string; type: "boolean" | "color" | "enum" | "number" | "string"; default?: boolean | number | string; description?: string; // one line under the label min?: number; // number only, inclusive max?: number; // number only, inclusive options?: { value: string; label: string }[]; // enum only, required}color renders the app’s theme swatches beside a text input, and its value is whatever
you would write in CSS — a hex value, rgb(…), a colour name, or a var(--token) that
follows the user’s theme. enum renders a select over options.
A value outside min/max, or not among options, falls back the same way a type
mismatch does: to your declared default, then to the type’s zero (an enum’s first
option). A default your own field would refuse is an install-time error.
‼️ None of this relieves you of checking the value yourself. Constraints are resolved against your current manifest by whatever Baram the user is running — one older than a constraint resolves the field without it.
context.subscriptions
Section titled “context.subscriptions”Disposable[] — every Disposable returned by commands.register,
events.on, ui.showStatusBarItem, ui.addStyle, ui.addSidebarPanel, and
ui.addSettingsTab is pushed here automatically and disposed when the
plugin is unloaded (reload, remove, or app shutdown). You don’t need to
track these yourself.

