Skip to content

Origin Approval and Connection State

Pedelec does not allow any web page to create local agent sessions or open a native directory picker automatically. The Chrome Extension identifies the page origin and requires user approval before the first createSession(), resumeSession(), or openWorkspace() from that origin.

const status = await pedelec.getApprovalStatus();
type ApprovalStatus = {
installed: boolean;
approved: boolean;
agentSessionsApproved?: boolean;
runtimeFullAccessApproved?: boolean;
origin: string | null;
appConnected: boolean;
};

true means the SDK reached the Pedelec extension and received a valid approval-status response.

false means the extension is currently unavailable to the page. Possible causes include:

  • the extension is not installed;
  • the extension is disabled or installed in another browser profile;
  • the page origin is not externally connectable;
  • the extension service worker or SDK port disconnected; or
  • the SDK was created outside a browser page.

Because several causes map to the same result, label this state “Pedelec extension unavailable” rather than “not installed” unless you have additional evidence.

true means the current Instance has all requested Origin grants in Extension-local storage: Agent Sessions, and Full Runtime Access when requested.

Approval is scoped to an origin, which includes scheme, hostname, and port. A development port change can require approval again.

The normalized origin of the current page, such as https://app.example.com or http://localhost:5173.

It can be null when the page does not have a verifiable HTTP or HTTPS origin.

This is the result of a dedicated non-sensitive Core ping. It does not imply origin approval or provider readiness. It never opens the approval popup, though the ping may use the Desktop auto-launch fallback.

Use checkAvailability() for a readiness check that includes Desktop without creating a session:

const availability = await pedelec.checkAvailability();

It returns Extension, approval, Desktop, and an optional normalized error. An unapproved origin does not open the popup, but its approval-status ping can probe Desktop. An approved origin additionally uses getSettings() as a protocol probe. launchAttempted means a ping or settings probe was sent, not that Desktop was proven to launch.

getApprovalStatus() only reads status and pings Core. It does not request approval. getSettings(), listProviders(), and openWorkspace() are sensitive Desktop APIs: they require origin approval and can trigger the approval popup. They expose only defaults, provider summaries, or an initialized workspace capability; use appConnected rather than listProviders() for connectivity.

The first operation that creates/resumes a session or opens a workspace triggers approval when needed:

await pedelec.createSession({ provider: "codex" });
// or
await pedelec.resumeSession(savedSessionId);
// or
const workspace = await pedelec.openWorkspace();

The extension queues the request, opens its popup, and waits for the user to approve or reject the site. After approval, the queued operation continues automatically.

This also applies to new Pedelec({ runtimeFullAccess: true }): its first createSession() opens the approval popup when either grant is missing. Both Agent Sessions and Full Runtime Access must be approved, even for a Session with runtimeFullAccess: false. Selecting only Agent Sessions displays Authorization Incomplete and rejects the pending operation with CREATE_SESSION_NOT_APPROVED. With both grants, Session false creates Sandbox mode and true requires Native confirmation of Full Access. A Standard Instance requesting a Full Session fails immediately with INVALID_INPUT.

The approval request has a timeout. Closing the popup without completing approval is treated as a rejection or incomplete approval.

Use separate checks for extension, runtime, and provider readiness. Approval status alone does not prove that the Desktop App is running.

UI state Condition Suggested action
Checking Status request is pending Disable the button and show progress
Extension unavailable installed === false Ask the user to install/enable the extension
Ready to approve Installed but approved === false Button label: “Connect Pedelec”
Connecting createSession() is pending Keep the popup instructions visible
Runtime unavailable Native/Core request fails Ask the user to start or repair the Desktop App
No provider No ProviderInfo.available is true Open provider setup guidance
Connected Session was created Show provider, effort level, and session status
Disconnected An active SDK port disconnects Disable send; the next new client operation retries the port, or explicitly resume a surviving session

Example:

async function connectPedelec() {
setConnectionState("checking");
const approval = await pedelec.getApprovalStatus();
if (!approval.installed) {
setConnectionState("extension-unavailable");
return;
}
setConnectionState(approval.approved ? "connecting" : "awaiting-approval");
try {
const providers = await pedelec.listProviders();
const provider = providers.find((item) => item.available);
if (!provider) {
setConnectionState("no-provider");
return;
}
const session = await pedelec.createSession({
provider: provider.code,
});
registerSession(session);
setConnectionState("connected");
} catch (error) {
routeConnectionError(error);
}
}
Code Meaning UI response
CREATE_SESSION_NOT_APPROVED The extension could not verify the origin, or another origin is already waiting Explain the origin conflict; retry after the other request finishes
APPROVAL_REJECTED The user rejected or closed the approval flow Return to the ready-to-approve state
APPROVAL_TIMEOUT Approval was not completed within the extension timeout Offer retry and tell the user to keep the popup open
OPEN_POPUP_FAILED Chrome could not open the extension popup programmatically Ask the user to click the Pedelec extension icon manually
SDK_ORIGIN_UNAVAILABLE The SDK caller origin could not be determined or forwarded Use a supported HTTP(S) page origin and reload
THREAD_ACCESS_DENIED A resumed or operated session belongs to a different origin Return to the owner origin or create a new session; do not treat the ID as a bearer token
STORAGE_ERROR Approved-origin storage could not be read or updated Suggest checking extension state or reinstalling if persistent
INVALID_ORIGIN A popup action received a non-HTTP(S) origin Use a supported page origin
Code Layer Typical response
EXTENSION_UNAVAILABLE Page → extension Check installation, browser profile, and supported origin
EXTENSION_DISCONNECTED Page → extension Stop the affected operation; the next new client operation retries, or explicitly resume a surviving session
NATIVE_HOST_UNAVAILABLE Extension → native host Start/repair the Desktop App installation
NATIVE_CONNECTION_CLOSED Extension → native host Ask the user to restart the Desktop App; retry a safe read operation
CORE_RUNTIME_UNAVAILABLE Native host → Core The background launch may have failed; open Desktop manually or repair its installation/launch configuration
IPC_UNAVAILABLE Local runtime IPC Restart the Desktop App; inspect local runtime logs
SDK_BRIDGE_TIMEOUT SDK request timeout Avoid immediate repeated writes; verify all downstream components
  • installed: true does not mean the Desktop App is running.
  • An approved origin does not mean a provider is available.
  • ProviderInfo.available: true does not guarantee a particular model identifier is valid.
  • Ollama provider availability does not guarantee that its server or model is ready.
  • A disconnected client reconnects lazily on the next new operation; an old session handle still requires explicit resume.

A robust connection screen presents the failing layer and the corrective action rather than one generic “connection failed” message.

Next, read Creating the client for client lifetime and bridge-timeout behavior.

Sandbox is the default. Full Access requires three separate conditions: an Instance created with runtimeFullAccess: true, explicit user approval of both Allow Agent Sessions and Allow Full Runtime Access in the Extension, and runtimeFullAccess: true on session creation.

const privileged = new Pedelec({ runtimeFullAccess: true });
// After the user explicitly grants both permissions in the Extension:
const sandbox = await privileged.createSession({ runtimeFullAccess: false });
const full = await privileged.createSession({ runtimeFullAccess: true });

Review the Extension permissions before creating sessions. An Instance requesting Full Access cannot create any session with only the Agent Sessions grant, including a Sandbox session. A standard Instance cannot request a Full Access session, even if another Instance on the same Origin has permission. Ordinary Origin approval never substitutes for the Full Access grant; the Popup offers an additional permission review with Full Access unchecked by default. getApprovalStatus() only reads status and does not open that review.

The Thread mode is fixed at creation and preserved on resume. Instances on the same Origin and Threads in the same Workspace retain their own requested modes. workspace.run() defaults to Sandbox and can request Full Access per invocation, and Provider sandbox settings are unchanged. Full Access changes the TypeScript Runtime’s OS permissions only. Revoking the Full Access grant rejects subsequent high-privilege execution and attempts to cancel affected running processes; unrelated Origins retain their grants.

Upgrade the SDK, Extension, and Desktop together when using Full Access. Missing mode acknowledgment is an error, never a successful downgrade. See Error Codes for authorization and protocol failures.