ReadAware

Plugin API reference

This page explains the development contract, which can be ahead of the latest release. The complete reference at the end lists every capability with its development version and its version in the latest release, the permission it needs, and each method's resolved signature and documentation. The Capabilities Explorer offers the same catalog interactively. The public plugin repository's types match the latest release.

Package and manifest

A plugin contains manifest.json and a self-contained ES module, normally main.js. Keep source and required assets with the package for review.

FieldMeaning
id, name, versionStable namespace, display name, and package version. The ID matches the folder name.
schemaVersionPositive integer for the plugin's private data schema; independent of package version.
requiresCapability IDs and semver ranges, grouped into domains, contributions, services, and schemas.
permissionsSemantic authority, such as library:read or service:llm.
settingsAccessSeparate discover, read, and write grants for exact paths or explicit section groups.
networkAccessAllowed HTTP(S) origins for Network 2.x; required alongside service:network.
minAppVersionOptional app-version floor, in addition to capability requirements.
mainRelative entry module; defaults to main.js.
settings, schedules, themes, fontsHost-interpreted declarations.
servicesVersioned, typed module service exports for cross-plugin calls.

There is no manifest field that grants arbitrary filesystem, SQL, DOM, or native IPC access.

Context and object scope

The host calls activate(ctx) with ctx.domains, ctx.contributions, and ctx.services, plus the manifest, locale, app version, lifecycle phase, capability versions, and immutable book grant.

ctx.grants.book is all, current, or a specified book. The host selects it through consent. Reading, memory, conversations, commands, and resources preserve that scope across calls and callbacks. A current-book change can invalidate outstanding reads, handles, proposals, and observations.

Domain write permission includes read. Settings grants remain separate by operation. Permission-gated namespaces or methods can be absent; host-side checks still run on every call. Use ctx.services.session.operationAvailability(...) for supported preflight queries, and handle execution failure even after a positive result.

Domains

DomainAvailable workBoundaries
libraryBooks and collections, TOCs, exact location search, ranges, references and images, imports, text tasks, metadata, duplicate merges, and removal.Source versions, book scope, bounded reads, actor-owned tasks, and separate file-cleanup receipts.
readingSession snapshots, navigation, selection, playback and mode controls, progress, reading time and insights.Current session guards, settled versus pending state, provider availability, and cancellation.
annotationsPages, inspection and observations; create highlights or notes; conditional edit/delete batches.Use the revision observed before the user's decision. Captured ranges also require Library access.
conversationsAuthorized transcripts, stored summaries, runtime and turn-request state; thread controls and proposed turns.Host approval starts a proposed turn. Global-thread operations require all-books access. Plugins do not replace the chat runtime.
settingsCatalog discovery, resolved snapshots, options, model metadata, observation, updates and reading resets.Exact paths, target policy, and additional authority for external provider work.
memorySearch and pages, inspection, correction/forgetting, profiles, entities, classification, graphs and tasks, context archives.Book grants and conditional revisions. Global identity/profile operations require all-books access; generation also needs model authority.

Source text and navigation

Use library.queries.books.searchLocations for navigable source matches and readRange for bounded source text. Preserve the returned source version and location. Derived searchText hits are previews, not interchangeable navigation anchors. Explicit text preparation returns a task whose progress and outcome must be observed.

Conditional writes

Inspect the current object and retain its revision before showing an edit. Submit the conditional mutation against that revision. On conflict, reread and let the user decide; silently replacing the expected revision would overwrite another change.

annotations.commands.applyChanges, memory mutations, private document commits, and transaction previews each have their own typed contract. Ordinary commands are not automatically undoable or distributed transactions.

Observations and reactions

Use authorized observations for current state and committed subscriptions for events. A sequence number can order deliveries without being a database cursor or a conditional-write revision. Failed observations must remain distinguishable from empty results.

Use ctx.withEvent(delivery) for automatic follow-up work and stable rule IDs on causal subscriptions where required. Preserve the bound context through asynchronous calls. The host rejects causal cycles and expired deliveries; independent user actions use the original context.

Contributions

ContributionWhat the plugin supplies
selectionActions, headerActions, contextActions, commands, uriHandlersActions at typed host surfaces, palette commands, and namespaced URI handling.
settingsOptionsDynamic options for a declared plugin setting.
voiceProviders, contentProviders, readerModesAudio synthesis, virtual-book content, and bundled reader segmentation modes.
agentTools, agentContextProviders, agentRetrievalProvidersTools, bounded per-turn context, and searchable plugin-owned sources.
memoryCandidateProvidersCandidate memories for host validation and acceptance.
themes, fontsManifest-declared appearance choices.
syncTransportsStorage of opaque encrypted sync envelopes and meta objects.

Actions can update their owned visible/enabled/checked state where supported. Registrations and disposables belong to one activation. Returning a view does not grant the callback extra domain authority.

Memory candidates and direct Memory commands are distinct paths: candidates go through host acceptance, while direct commands require the appropriate Memory grant and revision. Neither permits injecting system rules or replacing the core agent.

Host services

ServiceUse it forKey limit
storagePrivate KV, document collections, conditional commits, pages, observations and usage policies.Plugin namespace and quotas; stale cursors require a fresh baseline.
resourcesUser-picked files/directories, sealed byte handles, exports, images and private binary assets.No ambient paths. Handles have owners, limits and lifetimes.
secretsPlugin-private encrypted credential slots.No access to another plugin's secrets.
networkOrigin-scoped HTTP, bounded buffered requests and streaming.Every redirect is checked; no automatic replay of arbitrary writes.
llmText or structured inference, streaming, image resources, request receipts and budgets.User configuration, privacy rules, cancellation, and host/provider limits.
clipboardWrite text or a sealed image.Explicit permission and supported resource type.
uiViews, toast, native save/open flows, workspace and command navigation, reader panels and windows.Method-specific domain grants and host-owned presentation.
sessionNon-sensitive environment metadata and operation availability.No old reading-session subscription; use the Reading domain.
schedulesDeclared recurring handlers and owned deferred requests.Work runs while the app is open; timing is not exact.
jobsSupported durable plans, checkpoints, observation and control.Typed host operations, not arbitrary JavaScript execution.
changesScoped persistent change cursors.Reload hints, not a raw event log or historical values.
transactionsPreview, commit, receipt lookup and conditional undo preview.Supported local operations and original grants; unknown outcomes require receipt lookup.
pluginsInspect registrations, observe changes, discover and invoke typed plugin services.Caller/callee authority intersection, scope, versions, and isolated service execution.
maintenanceStatus and host-owned backup, connection-test and update flows.The host keeps credentials, file dialogs and consequential confirmation.
syncAuthorized sync status, backlog and host-managed account or sync flows.No encryption keys or raw account credentials.
diagnostics, loggingReviewed diagnostic exports and bounded structured developer events.No arbitrary content, secrets or automatic reporting through the log API.

Network and inference

Network 2.x needs both a semantic permission and explicit origins:

json
{
  "requires": { "services": { "network": "^2.2.0" } },
  "permissions": ["service:network"],
  "networkAccess": { "origins": ["https://api.example.com"] }
}

Replace the example origin with the endpoint you actually use. Origins include scheme, host and port; they are not URL paths or subdomain globs. Redirects must remain authorized. Streaming callers close owned streams when done. Optional safe retry is limited to supported read requests before a response is delivered; cancellation does not roll back a remote side effect.

For inference, use readingContext for book context so the host can apply privacy and scope rules. Use sealed resource IDs for supported images. Request metadata and output budgets help control work; they are not a billing statement or a guarantee of provider compliance.

Background work and transactions

Use a schedule to arrange a handler invocation, an owned deferred request for later work while the app runs, and a durable job only when its typed plan supports the operation. Restart recovery can require attention rather than blindly repeating an uncertain external result.

Transactions combine supported settings, private-document and domain operations under the original grants. Preview freezes the proposed work; commit consumes that preview. After an unknown response, query the receipt before retrying. Undo is conditional on the state still matching the prior result.

Cross-plugin services

Declare service ID, version, scope, required permissions, and input/output schemas in the provider manifest, and export its handler in the module's services object. Discover and call it through the Plugins service. The host runs a fresh isolated service realm with intersected authority; it does not activate the provider's ordinary UI runtime for the call. Agent-originated calls retain their approval requirement.

Views, settings, themes and fonts

Plugins return declarative view data. The host renders lists, forms, markdown, details and supported block layouts. Use typed view results and live view updates; keep loading, conflict, empty and error states distinct. No React, DOM, iframe or arbitrary CSS is available to plugin code.

Settings fields are rendered by the host. Secret fields write into encrypted secret slots and do not become ordinary form values or model-visible settings. Supplying a theme or font needs ui:themes; selecting one uses the corresponding Settings write grant.

Lifecycle and compatibility

  1. Activating: supported reads and registrations; staged contributions are not yet visible.
  2. Migrating: private storage only, before committing a changed schema.
  3. Active: promoted handlers may use granted capabilities.

The host health-checks and promotes a candidate after activation and any migration succeed. Failure restores the previous package and data. Unload releases registrations, callbacks and owned resources; durable data follows its separate retention contract. In current development, uninstall removes private document collections and binary assets while retaining the defined KV/secret/schema state for reinstall.

Declare each used capability and schema independently. A version number proves contract compatibility, not that every operating system, provider or failure case has passed end-to-end acceptance. Verify the actual desktop workflow you ship.

Build a plugin · Capabilities Explorer · Publishing

Complete reference

Every capability of the development contract, grouped by family. A plugin meant for the app people use today should require the version listed for the latest release.

Domains

domains:library

Inspect books, source text, TOCs, exact locations, ranges, images and collections; import, organize and manage text tasks.

  • Development: v1.35.0
  • ReadAware 0.6.7: v1.35.0
  • Authority: library:read / library:write
ctx.domains.library.commands.books.addVirtualBook
(input: { providerId: string; key: string; title: string; author?: string; }): Promise<BookSummary>
ctx.domains.library.commands.books.cancelImportTask
(taskId: string): Promise<BookImportTaskSnapshot>
ctx.domains.library.commands.books.cancelTextTask
(bookId: string, taskId: string): Promise<BookTextTaskSnapshot>

Cancels only this activation's request; shared work or dispatched writes may continue.

ctx.domains.library.commands.books.editMetadata
(bookId: string, patch: { title?: string; author?: string; }): Promise<void>
ctx.domains.library.commands.books.importBook
(input: { fileName: string; data: ArrayBuffer | Uint8Array; }, options?: PluginCallOptions): Promise<BookSummary>
ctx.domains.library.commands.books.importResource
(id: string, options?: PluginCallOptions): Promise<BookImportReceipt>

Library 1.19 adds per-call cancellation. Before the first durable write, cancellation prevents admission; afterward await the actual imported/duplicate receipt or failure. No whole-file transfer, opening or resource release.

ctx.domains.library.commands.books.invalidateVirtualBook
(input: { providerId: string; key: string; }): Promise<{ bookId: string; revision: string; }>

Announce already-saved source changes. Does not reload or move the reader. revision is a process-local invalidation fence, not a content hash. Library 1.15.

ctx.domains.library.commands.books.mergeDuplicates
(input: BookMergeRequest): Promise<BookMergeReceipt>

Conditional record merge with the host's deterministic keeper; not file deletion or undo.

ctx.domains.library.commands.books.pauseTextTask
(bookId: string, taskId: string): Promise<BookTextTaskSnapshot>
ctx.domains.library.commands.books.prepareText
(bookId: string, options?: BookTextPrepareOptions): Promise<BookTextTaskSnapshot>

Library 1.31: starts an actor-owned background request. A receipt is not completion. Current-book grants fence admission and the lease through pause/resume; switching books cancels only this request, without undoing accepted writes.

ctx.domains.library.commands.books.remove
(bookId: string): Promise<void>
ctx.domains.library.commands.books.removeMany
(bookIds: string[]): Promise<BookRemovalReceipt>

1-1000 IDs, deduplicated. Atomic record deletion; local file release is separately reported.

ctx.domains.library.commands.books.removeVirtualBook
(input: { providerId: string; key: string; expectedBookId?: string; }): Promise<void>
ctx.domains.library.commands.books.resumeTextTask
(bookId: string, taskId: string): Promise<BookTextTaskSnapshot>

Library 1.21: reacquires this paused request using saved checkpoints and the same handle.

ctx.domains.library.commands.books.retryEnrichment
(bookId: string): Promise<BookEnrichmentReceipt>

Retry unchecked covers and missing/filename-derived metadata using the shared queue, without forcing replacement or download.

ctx.domains.library.commands.books.retryRemovalCleanup
(bookIds: string[]): Promise<BookFileReleaseReceipt>

Retry file release only. Refuses any ID now present in the library; never deletes records.

ctx.domains.library.commands.books.setStarred
(bookId: string, starred: boolean): Promise<void>
ctx.domains.library.commands.books.setTextTaskPriority
(bookId: string, taskId: string, priority: BookTextPriority): Promise<BookTextTaskSnapshot>

Library 1.21: pauses only this request by releasing its lease; other consumers and dispatched I/O may continue.

ctx.domains.library.commands.books.startImport
(input: BookImportRequest, options?: PluginCallOptions): Promise<BookImportTaskSnapshot>

Start a task over owned sealed resources or <=64 MiB file bytes (wire limits still apply). Queued is not imported. options.signal cancels admission only; use cancelImportTask after the receipt. At most 2 physical task executions per activation, 4 in the app; direct imports/picker jobs are outside this task quota. Tasks do not resume after restart. Accepted writes finish despite cancellation.

ctx.domains.library.commands.collections.assignBooks
(bookIds: string[], collectionId: string | null): Promise<void>
ctx.domains.library.commands.collections.create
(name: string): Promise<CollectionSummary>
ctx.domains.library.commands.collections.remove
(collectionId: string): Promise<void>
ctx.domains.library.commands.collections.rename
(collectionId: string, name: string): Promise<void>
ctx.domains.library.events.observeContentState
(bookId: string, handler: PluginObservationHandler<BookContentObservation>, options?: { ruleId?: string; }): PluginDisposable
ctx.domains.library.events.observeEnrichment
(bookId: string, handler: PluginObservationHandler<BookEnrichmentObservation>, options?: { ruleId?: string; }): PluginDisposable
ctx.domains.library.events.observeImportTask
(taskId: string, handler: PluginObservationHandler<BookImportTaskSnapshot>, options?: { ruleId?: string; }): PluginDisposable

Initial snapshot and coalesced monotonic revisions, including terminal failures.

ctx.domains.library.events.observeInvalidation
(handler: PluginObservationHandler<ProjectionInvalidation>): PluginDisposable

Initial and coalesced reload hints, including remote projection changes. Re-query authorized data; not an event log or a conditional-write token.

ctx.domains.library.events.observeTextTask
(bookId: string, taskId: string, handler: PluginObservationHandler<BookTextTaskSnapshot>, options?: { ruleId?: string; }): PluginDisposable

Library 1.32: serial reaction deliveries retain task and history-write sources.

ctx.domains.library.events.subscribe
<K>(event: K, handler: (event: PluginDomainEvent<K>) => unknown, options?: { ignoreSelf?: boolean; ruleId?: string; }): PluginDisposable
ctx.domains.library.queries.books.get
(bookId: string): Promise<BookSummary | null>
ctx.domains.library.queries.books.getChapterText
(bookId: string, chapterIndex: number): Promise<string | null>
ctx.domains.library.queries.books.getContentState
(bookId: string, options?: PluginCallOptions): Promise<BookContentState>

Source metadata only; never loads a provider or reveals reading state. Library 1.16.

ctx.domains.library.queries.books.getEnrichment
(bookId: string): Promise<BookEnrichmentSnapshot>

Library 1.9: local cover/source state and the latest process-local enrichment attempt.

ctx.domains.library.queries.books.getImportTask
(taskId: string, waitMs?: number, options?: PluginCallOptions): Promise<BookImportTaskSnapshot>

waitMs (0..30000) waits for terminal state or returns current progress at the deadline. Cancelling this query stops observation only.

ctx.domains.library.queries.books.getNavigationToc
(bookId: string, options?: PluginCallOptions): Promise<BookNavigationToc>
ctx.domains.library.queries.books.getTextState
(bookId: string): Promise<BookTextSnapshot>

Read-only derived-text state. Never starts parsing, fetching, or extraction.

ctx.domains.library.queries.books.getTextTask
(bookId: string, taskId: string): Promise<BookTextTaskSnapshot>
ctx.domains.library.queries.books.getToc
(bookId: string): Promise<ChapterRef[]>
ctx.domains.library.queries.books.inspectResource
(id: string, options?: PluginCallOptions): Promise<BookInspection>

Initialize this activation's sealed resource with the reader parser; no import.

ctx.domains.library.queries.books.list
(): Promise<BookSummary[]>
ctx.domains.library.queries.books.listDuplicates
(query?: DuplicateBookQuery): Promise<DuplicateBookPage>

Library 1.10: same-content groups; live offset pages, limit 1-50.

ctx.domains.library.queries.books.listFormats
(): Promise<BookFormatCapability[]>

Library 1.11: import routing hints; extensions alone do not prove readability.

ctx.domains.library.queries.books.listImages
(input: BookReferencesQuery, options?: PluginCallOptions): Promise<BookImagesPage>

Library 1.29: section-local img/SVG, srcset/authored CSS and PDF image candidates. No remote fetch; PDF operator inspection can decode objects.

ctx.domains.library.queries.books.listImportTasks
(): Promise<BookImportTaskSnapshot[]>
ctx.domains.library.queries.books.listNavigationTargets
(input: BookNavigationTargetsQuery, options?: PluginCallOptions): Promise<BookNavigationTargetsPage>

Library 1.14: bounded source-section or author-supplied page-label catalog; not screen page counts.

ctx.domains.library.queries.books.listReferences
(input: BookReferencesQuery, options?: PluginCallOptions): Promise<BookReferencesPage>

Library 1.12: versioned section references, not extracted chapter indices.

ctx.domains.library.queries.books.listRemovalCleanup
(query?: BookRemovalCleanupQuery): Promise<BookRemovalCleanupPage>

Durable device-local pending file cleanup, including after view/plugin restart. Live keyset page, limit 1-100 (default 50).

ctx.domains.library.queries.books.listTextTaskHistory
(bookId: string, query?: BookTextTaskHistoryQuery): Promise<BookTextTaskHistoryPage>
ctx.domains.library.queries.books.listTextTasks
(bookId: string): Promise<BookTextTaskSnapshot[]>
ctx.domains.library.queries.books.openImageResource
(input: BookImageQuery): Promise<BookImageResource>

Seal an embedded image as this activation's ResourceRef; does not display it or decode pixels.

ctx.domains.library.queries.books.previewMerge
(bookId: string): Promise<BookMergePreview | null>
ctx.domains.library.queries.books.readRange
(input: BookRangeQuery, options?: PluginCallOptions): Promise<BookRangePage>
ctx.domains.library.queries.books.readReference
(input: BookReferenceQuery, options?: PluginCallOptions): Promise<BookReferencePreview>

Plain-text preview and resolved navigation location; never fetches or opens an external URL.

ctx.domains.library.queries.books.resolveId
(bookId: string): Promise<string | null>

Current book ID or merge redirect, null if neither points to a living book.

ctx.domains.library.queries.books.searchLocations
(input: BookLocationSearch, options?: PluginCallOptions): Promise<BookLocationSearchPage>
ctx.domains.library.queries.books.searchText
(input: BookTextSearch, options?: PluginCallOptions): Promise<BookTextHit[]>

Multi-query derived prose search. Single-book may prepare text; shelf search never does. Results are not navigation locations.

ctx.domains.library.queries.collections.booksIn
(collectionId: string): Promise<string[]>
ctx.domains.library.queries.collections.list
(): Promise<CollectionSummary[]>

domains:reading

Observe reading sessions, navigate and select text, control playback and modes, and query progress, time and insights.

  • Development: v2.24.0
  • ReadAware 0.6.7: v2.24.0
  • Authority: reading:read / reading:write
ctx.domains.reading.commands.back
(guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingNavigationReceipt>
ctx.domains.reading.commands.clearSelection
(expectedId: string, guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingSelectionReceipt>

Clears only the observed selection ID; a replacement selection is never silently cleared.

ctx.domains.reading.commands.close
(guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<void>
ctx.domains.reading.commands.configureMode
(input: ReadingModeConfiguration, guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingModeReceipt>

Configure the host mode; modeKey guards the current provider, selectModeKey selects from session().mode.availableModes. Resolves after real indexing (ready/empty) or deactivation. Failed indexing rejects. Disabling the caller cancels an unfinished change; completed mode preferences remain.

ctx.domains.reading.commands.controlPlayback
(action: "start" | "stop", guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingPlaybackReceipt>

Start resolves on actual audio start. Stop is idempotent; disabling the initiating plugin stops its playback.

ctx.domains.reading.commands.forward
(guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingNavigationReceipt>
ctx.domains.reading.commands.goTo
(target: ReadingTarget, options?: PluginCallOptions): Promise<ReadingNavigationReceipt>
ctx.domains.reading.commands.openBook
(bookId: string, options?: PluginCallOptions): Promise<ReadingNavigationReceipt>
ctx.domains.reading.commands.putEmphasis
(input: ReadingEmphasisWrite, guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingEmphasisReceipt>

Temporary owned marks, not annotations. No navigation; replacement requires an observed revision.

ctx.domains.reading.commands.reload
(guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingNavigationReceipt>

Reading 2.21: reopen source; virtual sections with identical stable identity/content preserve their location across reorder. Stale/legacy virtual locators restart at the beginning; files still restart. Whole-book contentVersion guards remain strict.

ctx.domains.reading.commands.removeEmphasis
(input: ReadingEmphasisRef, guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingEmphasisRemoval>
ctx.domains.reading.commands.returnToMode
(guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingNavigationReceipt>

Return to the versioned resting unit; wait for renderer navigation and unit restoration before committing history.

ctx.domains.reading.commands.selectRange
(range: BookTextRange, guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingSelectionReceipt>

Requires this book to be open; validates its source range, navigates, then waits for the selection overlay commit.

ctx.domains.reading.commands.setControls
(visible: boolean, guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingControlsReceipt>

Set reader chrome visibility; completes after UI commit. Does not alter panel preferences or playback.

ctx.domains.reading.commands.setFinished
(bookId: string, finished: boolean): Promise<void>
ctx.domains.reading.commands.step
(direction: ReadingStep, guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingNavigationReceipt>

Reading 2.12: page, source-section and book-boundary navigation; section/boundary jumps enter history.

ctx.domains.reading.commands.stepMode
(direction: "next" | "previous", guard?: ReadingSessionGuard, options?: PluginCallOptions): Promise<ReadingModeStepReceipt>

Step one configured text unit, across sections if necessary; reports book boundaries explicitly.

ctx.domains.reading.events.observeEmphasis
(handler: (snapshot: ReadingEmphasisSnapshot[], delivery?: PluginReactionEvent) => void | Promise<void>): PluginDisposable
ctx.domains.reading.events.observeSession
(handler: (snapshot: ReadingSessionSnapshot, delivery?: PluginReactionEvent) => void | Promise<void>, options?: { ruleId?: string; }): PluginDisposable

Immediate and subsequent snapshots carry a live reaction lease. Use withEvent for automatic writes; keep the original context for later user actions. A stable ruleId can resume job causality across activations.

ctx.domains.reading.events.observeTime
(query: ReadingTimeQuery, handler: (event: ReadingTimeObservation, delivery?: PluginReactionEvent) => void | Promise<void>, options?: { ruleId?: string; }): PluginDisposable

Immediate sample then a 1s minimum gap after each delivery. Errors are explicit; dispose stops further delivery. Reading 2.24: delivery retains sampling subscription ancestry across timers. It does not identify historical writers of the aggregate.

ctx.domains.reading.events.subscribe
<K>(event: K, handler: (event: PluginDomainEvent<K>) => unknown, options?: { ignoreSelf?: boolean; ruleId?: string; }): PluginDisposable
ctx.domains.reading.queries.emphasis
(): Promise<ReadingEmphasisSnapshot[]>

This activation's temporary marks only; attached does not mean visible in the viewport.

ctx.domains.reading.queries.session
(): Promise<ReadingSessionSnapshot>
ctx.domains.reading.queries.stats.forBook
(bookId: string): Promise<BookStats | null>
ctx.domains.reading.queries.stats.insights
(query?: ReadingInsightsQuery): Promise<ReadingInsights>
ctx.domains.reading.queries.stats.list
(): Promise<BookStats[]>
ctx.domains.reading.queries.stats.overview
(): Promise<StatsOverview>
ctx.domains.reading.queries.stats.time
(query?: ReadingTimeQuery): Promise<ReadingTimeSnapshot>

Atomic settled + pending time, with native sampling clock. Reading >=2.7.

domains:annotations

Page, inspect and observe highlights and notes; create them or apply revision-checked edits and deletes.

  • Development: v2.2.0
  • ReadAware 0.6.7: v2.2.0
  • Authority: annotations:read / annotations:write
ctx.domains.annotations.commands.applyChanges
(changes: AnnotationMutation[]): Promise<AnnotationCommitResult>

Since 2.0 this is the only edit/delete entry. Use the revision observed before the user's decision; 1..100 distinct items, all commit or none.

ctx.domains.annotations.commands.createHighlight
(input: { range?: BookTextRange; bookId: string; text: string; anchor?: string | null; chapterHref?: string | null; color?: HighlightColor; style?: HighlightStyle; }): Promise<HighlightItem>

annotations >=2.1: range validates and preserves the captured source; requires library:read.

ctx.domains.annotations.commands.createNote
(input: { range?: BookTextRange; bookId: string; body: string; quotedText?: string; anchor?: string | null; chapterHref?: string | null; }): Promise<NoteItem>
ctx.domains.annotations.events.observe
(query: AnnotationObservationQuery, handler: PluginObservationHandler<AnnotationObservation>): PluginDisposable

Since 1.4. Initial authorized snapshot, then changed results/errors/recovery. Disposal ends polling.

ctx.domains.annotations.events.subscribe
<K>(event: K, handler: (event: PluginDomainEvent<K>) => unknown, options?: { ignoreSelf?: boolean; ruleId?: string; }): PluginDisposable
ctx.domains.annotations.queries.get
(annotationId: string): Promise<AnnotationItem | null>

annotations >=1.1.0. Missing IDs return null; read failures reject.

ctx.domains.annotations.queries.inspect
(annotationId: string): Promise<AnnotationSnapshot | null>

annotations >=1.3.0. Read an item and its conditional-write token atomically.

ctx.domains.annotations.queries.list
(filter?: { bookId?: string; kind?: "highlight" | "note" | "ask"; query?: string; }): Promise<AnnotationItem[]>
ctx.domains.annotations.queries.page
(input?: AnnotationPageQuery): Promise<AnnotationPage>

annotations >=1.2.0. Live keyset page, not a frozen snapshot across calls.

domains:conversations

Read authorized transcripts, summaries and runtime state; propose turns, manage threads and use approved stop or clear controls.

  • Development: v1.6.0
  • ReadAware 0.6.7: v1.6.0
  • Authority: conversations:read / conversations:write
ctx.domains.conversations.commands.cancelTurnRequest
(id: string): Promise<ConversationTurnRequestSnapshot>
ctx.domains.conversations.commands.clear
(target: ConversationTarget): Promise<ConversationControlReceipt>

Clears transcript/hidden thread state after draining turns, not long-term memory or event history.

ctx.domains.conversations.commands.createThread
(): Promise<ConversationControlReceipt & { draft: true; }>

Creates and selects a global draft; no transcript row until the first message. Does not navigate the app.

ctx.domains.conversations.commands.requestTurn
(request: ConversationTurnRequest): Promise<ConversationTurnRequestSnapshot>

Requires a mounted conversation. Only a host UI confirmation can adopt/send/retry; receipt is not a completed turn.

ctx.domains.conversations.commands.selectThread
(threadId: string): Promise<ConversationControlReceipt>
ctx.domains.conversations.commands.stop
(target: ConversationTarget): Promise<ConversationControlReceipt>

Stops live UI turns and waits for their final transcript writes. Does not undo tool effects.

ctx.domains.conversations.events.observeInvalidation
(handler: PluginObservationHandler<ProjectionInvalidation>): PluginDisposable
ctx.domains.conversations.events.observeRuntime
(handler: PluginObservationHandler<PluginConversationRuntimeSnapshot>, options?: { ruleId?: string; }): PluginDisposable

Conversations 1.6: serial reaction deliveries, with an optional stable rule ID.

ctx.domains.conversations.events.subscribe
<K>(event: K, handler: (event: PluginDomainEvent<K>) => unknown, options?: { ignoreSelf?: boolean; ruleId?: string; }): PluginDisposable
ctx.domains.conversations.queries.getBookThread
(bookId: string): Promise<ChatMessageSummary[]>
ctx.domains.conversations.queries.getInsights
(target: ConversationTarget): Promise<string | null>

Conversations 1.4: stored rolling summary of a book/global thread, or null. No generation, freshness guarantee, raw runtime state or summary writes.

ctx.domains.conversations.queries.getThread
(threadId: string): Promise<ChatMessageSummary[]>
ctx.domains.conversations.queries.listThreads
(): Promise<ThreadSummary[]>
ctx.domains.conversations.queries.runtime
(): Promise<PluginConversationRuntimeSnapshot>
ctx.domains.conversations.queries.turnRequests
(): Promise<ConversationTurnRequestSnapshot[]>

Up to 128 recently retained host requests, filtered to this actor; no text or other actors' requests.

domains:settings

Discover exact setting paths and options, read settled snapshots, observe changes and update supported targets.

  • Development: v1.11.0
  • ReadAware 0.6.7: v1.10.0
  • Authority: none
ctx.domains.settings.commands.refreshModelCatalog
(provider: string, options?: PluginCallOptions): Promise<ModelCatalogPage>

Settings 1.9: additionally requires service:network. Shared native refresh, not a connection test.

ctx.domains.settings.commands.resetReading
(request: ReadingSettingsReset): Promise<SettingsUpdateResult>

Settings 1.7: reset the whole reader-preference bundle; every reading path must be writable. defaults restores built-ins; inherit deletes active and remembered book overrides.

ctx.domains.settings.commands.update
(changes: SettingChange[]): Promise<SettingsUpdateResult>
ctx.domains.settings.events.subscribe
(handler: (event: SettingsChangedEvent & PluginReactionEvent) => unknown, options?: { ignoreSelf?: boolean; ruleId?: string; }): PluginDisposable
ctx.domains.settings.queries.discover
(query?: SettingsQuery): Promise<SettingCatalogEntry[]>
ctx.domains.settings.queries.modelCatalog
(query: ModelCatalogQuery): Promise<ModelCatalogPage>

Settings 1.9: cached public model metadata; discover access to primaryModel or fastModel. No network.

ctx.domains.settings.queries.observe
(query: SettingsQuery, handler: PluginObservationHandler<SettingsObservation>): PluginDisposable

Settled snapshots after native, domain, remote, restore and catalog changes. Coalesces slow callbacks.

ctx.domains.settings.queries.options
(query: SettingsOptionsQuery): Promise<SettingsOptionsPage>

Settings 1.8: bounded options; same path grants as discover. Includes installed system families for reading/content fonts without font paths or bytes. Since 1.10, dynamicOptions fields invoke the registered owning provider with saved non-secret form values, never caller-supplied values. Network-enabled providers additionally require this caller's service:network permission. Results are cached for 60 seconds, at most 16 lists / 2000 options per list, 512 characters per label/value and 1 MiB of label/value JSON. Pages retain the returned revision; changed settings/provider or expiry require restart. Four provider loads host-wide, 10-second wait; already-started provider work is not cancelled by this deadline or caller retirement. No writes/synthesis. Plugin-owned option queries require the caller's active phase, not activation/migration. Empty results still allow manual values; provider failures remain failures.

ctx.domains.settings.queries.read
(path: string, target?: SettingsQueryTarget): Promise<SettingReadResult>
ctx.domains.settings.queries.snapshot
(query?: SettingsQuery): Promise<SettingsSnapshot>

Since settings 1.3: one host snapshot after prior queued writes settle, filtered by exact path grants.

domains:memory

Search, page, inspect and correct memories; work with profiles, entities, classification, graphs and versioned context bundles.

  • Development: v2.8.0
  • ReadAware 0.6.7: v2.8.0
  • Authority: memory:read / memory:write
ctx.domains.memory.commands.cancelGraphTask
(bookId: string, taskId: string): Promise<BookGraphTaskSnapshot>
ctx.domains.memory.commands.classify
(input: BookClassificationChange): Promise<BookClassificationReceipt>
ctx.domains.memory.commands.completeOnboarding
(input: OnboardingChange, options?: PluginCallOptions): Promise<OnboardingReceipt>

Memory 2.5: confirm the full summary AND seeds before calling. Reuse the same owner-local submissionId and exact candidate after a lost receipt; a different candidate requires a new id and renewed confirmation. Atomic, event-backed.

ctx.domains.memory.commands.context.capture
(selector: ContextBundleSelector, options?: PluginCallOptions): Promise<ContextBundleCaptureReceipt>
ctx.domains.memory.commands.decideEntity
(input: EntityDecision, options?: PluginCallOptions): Promise<EntityDecisionReceipt>

Memory 2.1: resolve an original member or merge known resolved classes using an observed entities1 revision. Present the exact change for confirmation first. Retains original definitions/aliases, may sync to other devices. No blind conflict retry. Cancellation prevents dispatch only; dispatched writes drain to their actual receipt. A transport timeout or lost Worker leaves the outcome unknown: reread, never retry blindly.

ctx.domains.memory.commands.mutate
(input: MemoryMutation): Promise<MemoryMutationReceipt>
ctx.domains.memory.commands.retryGraphTask
(bookId: string, taskId: string, options?: BookGraphTaskOptions): Promise<BookGraphTaskSnapshot>
ctx.domains.memory.commands.startGraphTask
(bookId: string, mode: "catch-up" | "rebuild", options?: BookGraphTaskOptions): Promise<BookGraphTaskSnapshot>
ctx.domains.memory.commands.updateProfile
(input: UserProfileChange): Promise<UserProfileReceipt>

Replace the event-backed summary using the observed profile2 revision. Present the complete candidate for user confirmation before calling. Empty text clears the summary, not memories or historical copies.

ctx.domains.memory.events.observe
(query: MemoryObservationQuery, handler: PluginObservationHandler<MemoryObservation>): PluginDisposable

Initial snapshot, then changed results/errors; bounded polling, not an event log. Plugins 1.5 supplies a separate reaction delivery, including graph task updates.

ctx.domains.memory.queries.bookGraph
(bookId: string, query?: BookGraphQuery): Promise<BookGraphResult>

memory >=2.6 only exposes current-source digests; chapter results carry contentVersion for navigation.

ctx.domains.memory.queries.classification
(bookId: string): Promise<BookClassificationSnapshot | null>
ctx.domains.memory.queries.context.export
(query: ContextBundleReadQuery, options?: PluginCallOptions): Promise<ResourceRef>
ctx.domains.memory.queries.context.history
(query: ContextBundleHistoryQuery, options?: PluginCallOptions): Promise<ContextBundleHistoryPage>
ctx.domains.memory.queries.context.read
(query: ContextBundleReadQuery, options?: PluginCallOptions): Promise<ContextBundle | null>
ctx.domains.memory.queries.entities
(query?: EntityQuery, options?: PluginCallOptions): Promise<EntityPage>

Global explicit identities, not book-digest characters. Row-bounded, revision-pinned pages. Memory 2.2 adds canonicalDefinition from the same snapshot. Historical field sizes are not bounded. Aborted/retired callers receive no late page.

ctx.domains.memory.queries.getGraphTask
(bookId: string, taskId: string): Promise<BookGraphTaskSnapshot>
ctx.domains.memory.queries.inspect
(id: string): Promise<MemorySnapshot | null>
ctx.domains.memory.queries.listGraphTasks
(bookId: string): Promise<BookGraphTaskSnapshot[]>
ctx.domains.memory.queries.page
(input: MemoryPageQuery): Promise<MemoryPage>
ctx.domains.memory.queries.profile
(query?: UserProfileQuery): Promise<UserProfilePage>

The event-backed summary projection; read grant, bounded revision-pinned pages.

ctx.domains.memory.queries.profileContext
(query?: ProfileInspectionQuery, options?: PluginCallOptions): Promise<ProfileInspectionPage>

Memory 2.3: inspect the generated summary and provenance, separately from curated profile(). Summary pages count UTF-16 units (4000 default, 16000 max); provenance pages count rows (25 default, 100 max; historical ID sizes are unbounded). Pin every page kind to pctx1. Stale text is inspectable, never current context. Invalid blocks expose no content. Current means source-consistent, not semantic verification or completed consolidation. entityEvidence IDs include proposed no-ops, not proof of emitted events. Read grant; no source text, transcripts, raw traits, registry writes or automatic inference.

ctx.domains.memory.queries.search
(input: MemoryQuery): Promise<MemoryRecord[]>

Contributions

contributions:uriHandlers

Handle namespaced ReadAware URI invocations through a registered action.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none
ctx.contributions.uriHandlers.register
(handler: PluginUriHandler): PluginActionRegistration

contributions:selectionActions

Add actions for captured selection, annotation or navigator input.

  • Development: v1.2.0
  • ReadAware 0.6.7: v1.2.0
  • Authority: none
ctx.contributions.selectionActions.register
(action: PluginSelectionAction): PluginActionRegistration

contributions:headerActions

Add reader, library or agent header actions with host-rendered views.

  • Development: v1.2.0
  • ReadAware 0.6.7: v1.2.0
  • Authority: none
ctx.contributions.headerActions.register
(action: PluginHeaderAction): PluginActionRegistration

contributions:contextActions

Add typed actions for supported book or collection context surfaces.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none
ctx.contributions.contextActions.register
(action: PluginContextAction): PluginActionRegistration

contributions:commands

Add namespaced command-palette actions and update their owned state.

  • Development: v1.1.0
  • ReadAware 0.6.7: v1.1.0
  • Authority: none
ctx.contributions.commands.register
(command: PluginCommand): PluginActionRegistration

contributions:settingsOptions

Resolve dynamic choices for a declared plugin setting.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none
ctx.contributions.settingsOptions.register
(fieldId: string, provider: (values: PluginFormValues) => PluginSelectOption[] | Promise<PluginSelectOption[]>): PluginDisposable

contributions:voiceProviders

Provide voice choices and encoded audio for read-aloud.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none
ctx.contributions.voiceProviders.register
(provider: PluginVoiceProvider): PluginDisposable

contributions:contentProviders

Provide sections for virtual books such as saved feeds.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none
ctx.contributions.contentProviders.register
(provider: { id: string; load(key: string): Promise<PluginBookContent>; }): PluginDisposable

contributions:agentTools

Register namespaced tools that the reading assistant can discover and call.

  • Development: v1.3.0
  • ReadAware 0.6.7: v1.3.0
  • Authority: agent:tools
ctx.contributions.agentTools.register
(tool: PluginToolDefinition): PluginActionRegistration

contributions:agentContextProviders

Supply bounded per-turn reference blocks and declared reading-intent sources.

  • Development: v1.1.0
  • ReadAware 0.6.7: v1.1.0
  • Authority: agent:context
ctx.contributions.agentContextProviders.register
(provider: PluginAgentContextProvider): PluginDisposable

contributions:agentRetrievalProviders

Expose searchable plugin-owned sources to the assistant.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: agent:retrieval
ctx.contributions.agentRetrievalProviders.register
(provider: PluginAgentRetrievalProvider): PluginDisposable

contributions:memoryCandidateProviders

Propose facts, preferences, insights or summaries for memory acceptance.

  • Development: v1.1.0
  • ReadAware 0.6.7: v1.1.0
  • Authority: agent:memory
ctx.contributions.memoryCandidateProviders.register
(provider: PluginMemoryCandidateProvider): PluginDisposable

contributions:themes

Declare semantic app and reader theme choices in the manifest.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: ui:themes

Manifest declaration

contributions:fonts

Declare font metadata and packaged font assets.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: ui:themes

Manifest declaration

contributions:syncTransports

Store and retrieve opaque encrypted events, blobs and key-material meta objects on an alternative remote.

  • Development: v2.0.0
  • ReadAware 0.6.7: v2.0.0
  • Authority: sync:transport
ctx.contributions.syncTransports.register
(transport: PluginSyncTransport): PluginDisposable

Services

services:storage

Use private KV and document collections, pages, observations, conditional commits and quota policies.

  • Development: v2.6.0
  • ReadAware 0.6.7: v2.6.0
  • Authority: none
ctx.services.storage.applyDocuments
(changes: PluginDocumentChange[]): Promise<PluginDocumentCommit>

Storage 2.1: atomically compare and apply 1..100 private document changes. Every expected revision is checked before any write. Does not include KV, core domain events, files, or another plugin's documents.

ctx.services.storage.collection
(name: string): PluginDocumentCollection

A named document collection — structured plugin-private data one tier above the KV (queryable, per-document, optionally book-anchored). Backed by the app's local store; lifecycle belongs to the plugin (uninstall clears it). bookId/anchor are provenance INDEXES, not ownership — documents survive the referenced book's deletion.

ctx.services.storage.documents(collection).delete
(id: string): Promise<void>
ctx.services.storage.documents(collection).get
<T>(id: string): Promise<PluginDocument<T> | null>
ctx.services.storage.documents(collection).list
<T>(filter?: { bookId?: string; limit?: number; oldestFirst?: boolean; }): Promise<PluginDocument<T>[]>

Newest-first by default.

ctx.services.storage.documents(collection).page
<T>(filter?: PluginDocumentPageFilter): Promise<PluginDocumentPage<T>>

Storage 2.1: 1..200 rows (default 50), 4 MiB JSON per page. Cursors bind namespace/filter/order and expire on any collection write. On stale-cursor restart rather than combining different snapshots.

ctx.services.storage.documents(collection).put
(id: string, data: unknown, options?: { bookId?: string; anchor?: string; }): Promise<void>
ctx.services.storage.flush
(): Promise<void>

Wait for outstanding writes in this plugin's namespace.

ctx.services.storage.get
<T>(key: string): T | null
ctx.services.storage.getDurable
<T>(key: string): Promise<T | null>

2.4: keys up to 1024 UTF-16 units, no NUL. Settle accepted writes, then read this private key from SQLite, not the optimistic mirror. Corrupt JSON rejects; null means absent or JSON null.

ctx.services.storage.observeDocuments
<T>(query: PluginDocumentObservationQuery, handler: PluginObservationHandler<PluginDocumentObservation<T>>): PluginDisposable

Storage 2.2: initial and changed private document query snapshots, including errors/recovery. At most 64 active observers per activation; reads and callbacks settle before the next one-second poll. Not a replayable write stream. Dispose or plugin retirement stops delivery; sequence is not CAS.

ctx.services.storage.onChange
(handler: PluginObservationHandler<{ kind: "changed"; }>, options?: { ruleId?: string; }): PluginDisposable

Fires when this plugin's namespace is written from OUTSIDE the plugin — its settings page, the reading agent, another surface editing the same object. Settings-key changes can also echo after own writes. Serial callbacks receive a reaction credential; use withEvent to preserve causes. No initial callback; intermediate changes coalesce. Use it to re-read (or re-derive from) settings you would otherwise have cached at activate().

ctx.services.storage.policy
(): Promise<PluginStoragePolicy>

Storage 2.5: own persisted usage and actual per-store policy. Null quota means no enforced total limit, not unlimited disk. Call flush first when awaiting this activation's pending writes. No names or secret values. Complete backup refers to full app backup, not reading/OPML exports.

ctx.services.storage.remove
(key: string): Promise<void>
ctx.services.storage.set
(key: string, value: unknown): Promise<void>

Reads update optimistically; resolve only after the write is durable.

services:secrets

Read and write credentials in plugin-private encrypted slots.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none
ctx.services.secrets.get
(key: string): Promise<string | null>
ctx.services.secrets.remove
(key: string): Promise<void>
ctx.services.secrets.set
(key: string, value: string): Promise<void>

services:ui

Publish views, show toast, save or open resources, navigate workspaces and commands, and control supported reader panels and windows.

  • Development: v1.17.0
  • ReadAware 0.6.7: v1.17.0
  • Authority: none
ctx.services.ui.commands.execute
(request: HostCommandRequest): Promise<HostCommandReceipt>

Library write plus each command's setting grant; opening/leaving a reader needs reading:write.

ctx.services.ui.commands.list
(): Promise<HostCommandSnapshot>
ctx.services.ui.commands.observe
(handler: PluginObservationHandler<HostCommandObservation>, options?: { ruleId?: string; }): PluginDisposable

UI 1.16: serial/coalesced snapshots with a reaction delivery and optional stable ruleId.

ctx.services.ui.exportFile
(file: PluginExportFile): Promise<boolean>
ctx.services.ui.openExternal
(url: string): Promise<void>

UI 1.7, requires service:network. Explicit user intent only; HTTP(S), no credentials or local schemes.

ctx.services.ui.publishView
(channel: PluginViewChannel, update: PluginViewUpdate): Promise<PluginViewUpdateReceipt>

Updates only this activation's visible frame. Revision is a nonnegative, increasing safe integer. Receipt confirms host acceptance, not paint; updates cannot navigate or replace the subscription.

ctx.services.ui.reader.closeReferencePreview
(id: string): Promise<ReaderReferenceCloseReceipt>

Only this activation's current preview ID; never closes a native or other owner's note.

ctx.services.ui.reader.focus
(target: ReaderFocusTarget, guard?: ReadingSessionGuard): Promise<ReaderFocusReceipt>

UI 1.14, reading:write. Focus an already visible semantic target, without opening or dismissing UI. not-focused is not success; close your own dialog before returning focus.

ctx.services.ui.reader.image.control
(request: ReaderImageRequest): Promise<ReaderImageReceipt>

reading:write; exact current viewer ID required. Pan deltas are fractions of its viewport.

ctx.services.ui.reader.image.observe
(handler: PluginObservationHandler<ReaderImageSnapshot | null>): PluginDisposable

Plugins 1.6 supplies a separate reaction delivery, including closed/null snapshots.

ctx.services.ui.reader.image.open
(query: BookImageQuery, guard?: ReadingSessionGuard): Promise<ReaderImageOpenReceipt>

UI 1.13: library read + reading write; opens an embedded image in the current book.

ctx.services.ui.reader.image.snapshot
(): Promise<ReaderImageSnapshot | null>
ctx.services.ui.reader.observe
(handler: PluginObservationHandler<ReaderPanelsSnapshot | null>): PluginDisposable

Plugins 1.6 supplies a separate reaction delivery; callbacks are serial and coalesced.

ctx.services.ui.reader.previewReference
(query: BookReferenceQuery, guard?: ReadingSessionGuard): Promise<ReaderReferencePreviewReceipt>

UI 1.8: also needs library:read. Open book only; resolved preview waits for DOM commit.

ctx.services.ui.reader.setPanel
(panel: ReaderPanel, open: boolean, guard?: ReadingSessionGuard): Promise<ReaderPanelReceipt>

Requires reading:write. Opening reveals controls; completion waits for persistence and DOM commit.

ctx.services.ui.reader.setWidth
(panel: ResizableReaderPanel, width: number, guard?: ReadingSessionGuard): Promise<ReaderPanelReceipt>

Persist a shared TOC/chat width (integer 240..640 CSS px); does not open it or focus.

ctx.services.ui.reader.snapshot
(): Promise<ReaderPanelsSnapshot | null>
ctx.services.ui.showToast
(message: PluginToast): void
ctx.services.ui.window.control
(request: HostWindowRequest): Promise<HostWindowReceipt>
ctx.services.ui.window.observe
(handler: PluginObservationHandler<HostWindowObservation>, options?: { ruleId?: string; }): PluginDisposable

UI 1.17: reaction delivery remains valid until the callback settles.

ctx.services.ui.window.snapshot
(): Promise<HostWindowSnapshot>
ctx.services.ui.workspace.navigate
(target: WorkspaceTarget, expectedRevision?: number): Promise<WorkspaceReceipt>

Library write grant; leaving an active reader additionally requires reading:write.

ctx.services.ui.workspace.observe
(query: WorkspaceQuery, handler: PluginObservationHandler<WorkspaceSnapshot | null>, options?: { ruleId?: string; }): PluginDisposable

UI 1.16: use the separate reaction delivery even for null/retired snapshots.

ctx.services.ui.workspace.snapshot
(query?: WorkspaceQuery): Promise<WorkspaceSnapshot>

services:schedules

Bind declared recurring handlers, inspect and control schedules, and manage owned deferred requests.

  • Development: v2.1.0
  • ReadAware 0.6.7: v2.1.0
  • Authority: none
ctx.services.schedules.bind
(scheduleId: string, run: (context: PluginScheduleRun, delivery?: PluginReactionEvent) => void | Promise<void>): PluginDisposable
ctx.services.schedules.cancelDeferred
(id: string, requestId: string, options?: PluginCallOptions): Promise<PluginDeferredReceipt>

Cancel exactly the queued ID, not an in-flight callback or a replacement request.

ctx.services.schedules.control
(id: string, action: "pause" | "resume" | "run"): Promise<PluginScheduleReceipt>

Pause/resume persist; run bypasses pause/cadence once. Neither pause nor cancellation undoes dispatched callback effects.

ctx.services.schedules.defer
(id: string, input: PluginDeferredRequest, options?: PluginCallOptions): Promise<PluginDeferredReceipt>

Schedules 2: enqueue one declared deferred task. Persists before acknowledgement. 1 second..7 days; idle means 5 seconds without host input. Never runs while closed. The most recent request ID is retained for retry; changed input conflicts, another queued ID is busy. A dispatched request is never automatically replayed after a crash. Inspect interrupted and decide explicitly.

ctx.services.schedules.list
(query?: Omit<PluginScheduleQuery, "pluginId">): Promise<PluginSchedulePage>

Bound schedules owned by this plugin only, with the latest persisted attempt/outcome.

ctx.services.schedules.observe
(query: Omit<PluginScheduleQuery, "pluginId">, handler: PluginObservationHandler<PluginSchedulePage>, options?: { ruleId?: string; }): PluginDisposable

services:jobs

Start, inspect and control durable plans built from supported host operations.

  • Development: v1.1.0
  • ReadAware 0.6.7: v1.1.0
  • Authority: none
ctx.services.jobs.control
(id: string, action: DurableJobControl, options?: PluginCallOptions): Promise<DurableJobSnapshot>
ctx.services.jobs.get
(id: string, options?: PluginCallOptions): Promise<DurableJobSnapshot>
ctx.services.jobs.list
(query?: { offset?: number; limit?: number; }, options?: PluginCallOptions): Promise<{ jobs: DurableJobSnapshot[]; nextOffset: number | null; }>
ctx.services.jobs.start
(plan: DurableJobPlan, options?: PluginCallOptions): Promise<DurableJobSnapshot>

jobs 1.1: event-bound starts preserve their source through restart. Every causal event subscription must have a stable ruleId. Unnamed reactions and isolated service invocations cannot create saved jobs.

services:changes

Open and read scoped change cursors that can be persisted across restarts.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none
ctx.services.changes.open
(query: ChangesQuery, options?: PluginCallOptions): Promise<{ cursor: string; }>

Open before loading a baseline. Persist the returned cursor only after processing each page. Expired cursors require a new baseline. Notices are conservative reload hints, not events or values; settings hints cover the authorized requested paths in a shared storage namespace.

ctx.services.changes.read
(query: ChangesQuery, cursor: string, limit?: number, options?: PluginCallOptions): Promise<ChangesPage>

services:transactions

Preview and commit supported local changes, inspect receipts and preview conditional undo.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none
ctx.services.transactions.commit
(previewId: string, options?: PluginCallOptions): Promise<AtomicReceipt>
ctx.services.transactions.preview
(operations: AtomicOperation[], options?: PluginCallOptions): Promise<AtomicPreview>
ctx.services.transactions.previewUndo
(receiptId: string, options?: PluginCallOptions): Promise<AtomicPreview>
ctx.services.transactions.receipt
(receiptId: string, options?: PluginCallOptions): Promise<AtomicReceipt | null>

services:session

Read environment metadata and check availability of supported operations.

  • Development: v2.18.0
  • ReadAware 0.6.7: v2.18.0
  • Authority: none
ctx.services.session.environment
(): Promise<HostEnvironmentSnapshot>

Fresh non-sensitive metadata; contains no reading or account state.

ctx.services.session.observeEnvironment
(handler: (snapshot: HostEnvironmentSnapshot, delivery?: PluginReactionEvent) => void | Promise<void>, options?: { ruleId?: string; }): PluginDisposable

Session 2.7: locale effects retain their requester; other system facts keep independent sources.

ctx.services.session.operationAvailability
(query: OperationAvailabilityQuery, options?: PluginCallOptions): Promise<OperationAvailability>

Session 2.11: inspect host command permissions/workspace guards and plugin service contract/authority/capacity (Agent approval remains required), export metadata/save entry and clipboard/browser entry availability (no OS access probe), window support/capacity/target state, sync connection/credentials/provider, inference, book-targeted playback/mode, text preparation and graph prerequisites without executing or probing. Missing permission returns only the permission condition. Unknown remote health is not a local refusal or a success guarantee.

services:plugins

Inspect installed plugins and registrations, observe changes, and discover or call typed plugin services.

  • Development: v1.10.0
  • ReadAware 0.6.7: v1.10.0
  • Authority: none
ctx.services.plugins.callService
(request: PluginServiceCall, options?: PluginCallOptions): Promise<PluginServiceReceipt>

Executes one declared export in a fresh restricted Worker. No live-root closures, callbacks, binary handles, automatic retries, or resources surviving the call.

ctx.services.plugins.contributions
(query?: PluginContributionQuery): Promise<PluginContributionPage>

Registered identities across extension points, never provider callbacks, data, settings or a grant to invoke another plugin. Offset pages may change.

ctx.services.plugins.list
(query?: PluginDirectoryQuery): Promise<PluginDirectoryPage>

Public installed metadata only, no settings, paths, secrets or raw errors.

ctx.services.plugins.listServices
(query?: PluginServiceQuery, options?: PluginCallOptions): Promise<PluginServicePage>

Plugins 1.8: authorized service contracts; discovery does not execute providers.

ctx.services.plugins.observe
(query: PluginDirectoryQuery, handler: PluginObservationHandler<PluginDirectoryPage>, options?: { ruleId?: string; }): PluginDisposable

Plugins 1.10: serial reaction deliveries with stable rule IDs; reload offset pages after changes.

ctx.services.plugins.observeContributions
(query: PluginContributionQuery, handler: PluginObservationHandler<PluginContributionPage>, options?: { ruleId?: string; }): PluginDisposable

services:maintenance

Inspect maintenance state and enter host-owned backup, connection-test, update or settings flows.

  • Development: v1.5.0
  • ReadAware 0.6.7: v1.5.0
  • Authority: none
ctx.services.maintenance.checkForUpdates
(): Promise<HostMaintenanceSnapshot>

Requires service:network. Uses the host release feed; no caller-supplied URL or silent installation.

ctx.services.maintenance.observe
(handler: PluginObservationHandler<HostMaintenanceSnapshot>, options?: { ruleId?: string; }): PluginDisposable
ctx.services.maintenance.openSettings
(surface: "updates" | "diagnostics" | "plugins" | "backup-import" | "backup-export" | "delete-data" | "ai-connection" | "data-location"): Promise<{ status: "opened"; surface: HostMaintenanceSurface; }>

Maintenance 1.4 adds data-location: shows the directory in host UI, never returns its path or opens the file manager. Also reveals updates/diagnostics/plugins/backup-import/backup-export/delete-data/ai-connection. Does not click controls, open file dialogs, approve installation or bypass typed DELETE.

ctx.services.maintenance.requestBackup
(action: BackupAction, options?: PluginCallOptions): Promise<BackupReceipt>

Reveals a host backup button and awaits the user's click and file dialog. Both directions use the complete encrypted archive (host-only password); import adds host review and confirmation, then reload. Retired v1 JSON library backups are rejected. No passwords, bytes or paths are returned.

ctx.services.maintenance.requestConnectionTest
(options?: PluginCallOptions): Promise<ConnectionTestReceipt>

Maintenance 1.3: reveal native AI test controls; only the user's click starts inference.

ctx.services.maintenance.snapshot
(): Promise<HostMaintenanceSnapshot>

services:diagnostics

Request supported diagnostic export or reporting flows.

  • Development: v1.2.0
  • ReadAware 0.6.7: v1.2.0
  • Authority: service:diagnostics
ctx.services.diagnostics.requestProjectionRepair
(options?: PluginCallOptions): Promise<ProjectionRepairReceipt>

Diagnostics 1.2: opens host confirmation; a committed repair requires reload.

ctx.services.diagnostics.requestReport
(action: DiagnosticsReportAction, options?: PluginCallOptions): Promise<DiagnosticsReportReceipt>
ctx.services.diagnostics.verifyProjections
(options?: PluginCallOptions): Promise<ProjectionVerification>

services:logging

Write bounded structured developer events and inspect logging policy.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none
ctx.services.logging.policy
(): Promise<{ levels: PluginLogEntry["level"][]; maxEntryChars: number; maxFields: number; perPluginLimit: number; appLimit: number; windowMs: number; delivery: "best-effort"; }>
ctx.services.logging.write
(entry: PluginLogEntry): Promise<PluginLogReceipt>

Logging 1.0: accepted means forwarded to the best-effort host logger, not durably stored or uploaded. Allowed during activation and migration. Debug is development-console-only. Retired activations cannot write.

services:resources

Pick files and directories, read or create sealed resources, export data, and store private binary assets.

  • Development: v1.5.0
  • ReadAware 0.6.7: v1.5.0
  • Authority: none
ctx.services.resources.append
(id: string, offset: number, data: ArrayBuffer | Uint8Array<ArrayBufferLike>): Promise<ResourceRef>
ctx.services.resources.assets.delete
(key: string, expectedRevision: string, options?: PluginCallOptions): Promise<{ deleted: true; cleanupPending: boolean; }>
ctx.services.resources.assets.get
(key: string, options?: PluginCallOptions): Promise<PluginAsset | null>
ctx.services.resources.assets.list
(query?: PluginAssetQuery, options?: PluginCallOptions): Promise<PluginAssetPage>
ctx.services.resources.assets.open
(key: string, expectedRevision: string, options?: PluginCallOptions): Promise<ResourceRef>
ctx.services.resources.assets.policy
(options?: PluginCallOptions): Promise<PluginAssetPolicy>
ctx.services.resources.assets.store
(resourceId: string, input: PluginAssetWrite, options?: PluginCallOptions): Promise<PluginAssetReceipt>
ctx.services.resources.commit
(id: string): Promise<ResourceRef>
ctx.services.resources.create
(options: ResourceCreateOptions): Promise<ResourceRef>
ctx.services.resources.listDirectory
(id: string, query?: ResourceDirectoryQuery): Promise<ResourceDirectoryPage>
ctx.services.resources.openAssociated
(id: string, options?: PluginCallOptions): Promise<{ opened: boolean; }>

Resources 1.5: host confirmation then OS association for a temporary document/media copy. No edit-back, arbitrary program/path, or context bundles. True is dispatch, not rendering.

ctx.services.resources.openBook
(bookId: string): Promise<ResourceRef | null>

Requires library:read. Original local file only; no implicit remote download.

ctx.services.resources.openCover
(bookId: string): Promise<ResourceRef | null>

Resources 1.1; requires library:read. No extraction/download when the cover is unavailable.

ctx.services.resources.openDirectoryFile
(id: string, relativePath: string): Promise<ResourceRef>
ctx.services.resources.pick
(options?: ResourcePickOptions): Promise<{ cancelled: boolean; resources: ResourceRef[]; }>
ctx.services.resources.pickDirectory
(): Promise<{ cancelled: boolean; directory: ResourceDirectoryRef | null; }>

Resources 1.4: reader-selected, read-only directory grants; four per activation, one hour. No ambient paths. Listings are live; openDirectoryFile seals the current file bytes.

ctx.services.resources.read
(id: string, offset: number, length: number): Promise<ResourceChunk>
ctx.services.resources.release
(id: string): Promise<void>

Also aborts uncommitted writes.

ctx.services.resources.releaseDirectory
(id: string): Promise<void>
ctx.services.resources.save
(id: string, filename?: string): Promise<{ saved: boolean; }>
ctx.services.resources.stat
(id: string): Promise<ResourceRef>

services:sync

Observe sync status and backlog, request sync, and enter host-managed account or connection flows.

  • Development: v1.2.0
  • ReadAware 0.6.7: v1.2.0
  • Authority: service:sync
ctx.services.sync.account
(): Promise<HostSyncAccount | null>

Explicit remote read of the account's tier, usage and limits; null without an account. No email, account ID, keys, session or billing ticket.

ctx.services.sync.backlog
(): Promise<{ events: number; blobs: number; }>

Events and blobs waiting to be pushed.

ctx.services.sync.connectionOptions
(): Promise<{ ref: string; label: string; }[]>

Registered backend references and display labels, never endpoint credentials.

ctx.services.sync.observe
(handler: PluginObservationHandler<HostSyncSnapshot>, options?: { ruleId?: string; }): PluginDisposable

Delivers each new sync snapshot (state, progress, completed cycles) while the handle lives.

ctx.services.sync.openSettings
(): Promise<{ status: "opened"; surface: "dataSync"; }>

Opens the host Data & Sync page; not a login, disconnect or purchase.

ctx.services.sync.requestFlow
(request: HostSyncFlowRequest, options?: PluginCallOptions): Promise<HostSyncFlowReceipt>

Host-owned connect, disconnect, account deletion, upgrade or billing flow. Waits for the final local outcome or external handoff; cancellation cannot undo a started operation.

ctx.services.sync.requestSync
(): Promise<HostSyncReceipt>

Runs one sync round on the configured backend (relay or a transport plugin such as WebDAV) and resolves when it has finished: completed, or already-running when a round was in progress (not queued again). Rejects with a coded error when no round can start (ui/unavailable) or the round fails (classified failures carry sync/* codes).

ctx.services.sync.snapshot
(): Promise<HostSyncSnapshot>

Current sync state: backend, connection, progress, last cycle and last error code.

services:network

Make origin-scoped HTTP requests or read bounded streams, with opt-in safe retries.

  • Development: v2.2.0
  • ReadAware 0.6.7: v2.2.0
  • Authority: service:network
ctx.services.network.closeStream
(id: string): Promise<void>

Idempotent for this activation's released/unknown IDs. Aborts pending reads; does not undo remote effects or remove data already saved by the plugin.

ctx.services.network.fetch
(input: string | URL | Request, init?: RequestInit, options?: { retry?: "none" | "safe"; }): Promise<Response>

Native HTTP; Request/init semantics and cancellation survive the Worker bridge. Bodies are buffered up to 64 MiB per direction. Calls have a 120s deadline; an abort does not undo a remote side effect already committed by the server. Network 2.0 requires networkAccess for the initial URL and each redirect. HTTPS -> HTTP redirects are denied. At most 10 redirects; manual returns the 3xx response, error rejects. Cross-origin hops drop authorization, proxy-authorization, cookie and referer; custom secret headers are the plugin's responsibility (use redirect:error for authenticated endpoints). Host/content-length are transport-owned. No implicit retry or cookie jar. Network 2.2: options.retry="safe" opts GET/HEAD without a body into at most two retries across the whole redirect chain, before response headers are returned. Other methods and all body reads are never replayed. The original deadline includes backoff; Retry-After above 30s returns the HTTP response. Attempts/uploads/read chunks share per-owner and host cumulative quotas; reactivation does not reset owner debt. policy() reports exact limits. Transport failures carry plugin/network-failed; explicit deadlines carry plugin/network-timeout, aborts plugin/cancelled. Existing structured codes survive unchanged. Unclassified native errors are not guessed from prose. HTTP error statuses still return Response; the consumer decides success.

ctx.services.network.openStream
(input: string | URL | Request, init?: RequestInit, options?: { retry?: "none" | "safe"; }): Promise<PluginNetworkStream>

Network 2.1: headers first; download at most 1 GiB without buffering the whole response. Uploads remain capped at 64 MiB. 8 active requests per activation / 32 host-wide, shared with fetch; no hidden durable queue. Optional safe retry applies only before this opening receipt, as in fetch. init.signal cancels OPENING only; after receipt use closeStream to cancel. Close in finally if not reading to EOF. 120s absolute lifetime, including headers/redirects/reads; unload cancels and drains native resources.

ctx.services.network.policy
(): Promise<PluginNetworkAccess & { maxRedirects: number; maxBodyBytes: number; timeoutMs: number; maxStreamBytes: number; maxChunkBytes: number; maxConcurrentRequests: number; maxHostConcurrentRequests: number; cumulative: { windowMs: number; maxOwnerRequests: number; maxHostRequests: number; maxOwnerBytes: number; maxHostBytes: number; maxOwners: number; }; retry: { maxRetries: number; baseDelayMs: number; maxDelayMs: number; statuses: readonly number[]; }; }>

Network 2.0: this activation's immutable authorization and transport limits. All-origins authorization is ["*"], not a guarantee of endpoint reachability.

ctx.services.network.readStream
(id: string, offset: number, maxBytes?: number): Promise<PluginNetworkChunk>

Sequential, non-replayable reads. offset must equal bytes already delivered. One outstanding read per stream; maxBytes defaults to 64 KiB, max 1 MiB. A lost read receipt is not safely retryable: close and restart explicitly.

services:llm

Request text, structured or streaming inference, use sealed image resources, and track request metadata and budgets.

  • Development: v1.6.0
  • ReadAware 0.6.7: v1.6.0
  • Authority: service:llm
ctx.services.llm.ask
(input: PluginInferenceInput & { schema?: never; onText?: (delta: string) => void; }): Promise<string>
(input: PluginInferenceInput & { schema: Record<string, unknown>; onText?: never; }): Promise<unknown>
ctx.services.llm.askDetailed
(input: PluginInferenceInput & { schema?: never; onText?: (delta: string) => void; }): Promise<InferenceResult<string>>
(input: PluginInferenceInput & { schema: Record<string, unknown>; onText?: never; }): Promise<InferenceResult<unknown>>

llm 1.3: same execution as ask, with per-attempt metadata on success. Includes structured retries; failure/cancellation rejects, not a billing receipt.

ctx.services.llm.cancelRequest
(requestId: string): Promise<InferenceRequestReceipt | null>

Requests cancellation independently of the ask RPC. The returned snapshot may still be running; query again for its outcome and provider settlement.

ctx.services.llm.getRequest
(requestId: string): Promise<InferenceRequestReceipt | null>

llm 1.6: last 64 named requests in this plugin's local private storage. Initial metadata commits before inference dispatch; no prompt/output is retained. Includes backup/rollback and uninstall cleanup, not roaming or billing history. requestAvailable identifies this activation's handle. An older unsettled record has interrupted=true: status is last observed, not proof it still runs remotely. No automatic retry/resume; historical IDs cannot control another activation. Late terminal usage is persisted; unknown/evicted IDs return null.

ctx.services.llm.listRequests
(): Promise<InferenceRequestReceipt[]>
ctx.services.llm.policy
(): Promise<{ defaultTimeoutMs: number; maxTimeoutMs: number; perPluginLimit: number; appLimit: number; maxOutputTokensLimit: number; maxImageCount: number; maxImageBytes: number; maxImageTotalBytes: number; maxTotalOutputTokensLimit: number; maxOutputCharsLimit: number; maxInputChars: number; }>

Plugin inference limits, not billing quotas. maxOutputTokensLimit since 1.3.

services:clipboard

Write text or a supported sealed image to the system clipboard.

  • Development: v1.1.0
  • ReadAware 0.6.7: v1.1.0
  • Authority: service:clipboard
ctx.services.clipboard.writeImage
(resourceId: string): Promise<ResourceImageReceipt>

Clipboard 1.1. This activation's sealed resource; raster decode stays in the host.

ctx.services.clipboard.writeText
(text: string): Promise<void>

Schemas

schemas:views

Describe host-rendered lists, forms, details, markdown and supported block layouts.

  • Development: v1.12.0
  • ReadAware 0.6.7: v1.12.0
  • Authority: none

Manifest declaration

schemas:settings

Declare typed plugin settings, conditional fields and dynamic option references.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: none

Manifest declaration

schemas:themes

Describe semantic application and reader palettes.

  • Development: v1.0.0
  • ReadAware 0.6.7: v1.0.0
  • Authority: ui:themes

Manifest declaration