ambleloft

Backend SDK and invocation context

@ambleloft/extension-sdk: register business operations, access project resources and manage extension state.

API REFERENCE

Browse contracts, signatures, fields and examples. Unspecified defaults are not inferred.

On this page

01Entry points and lifecycle

defineExtension accepts activate and optional deactivate; activate returns void or Promise<void>. The register handler name must match the manifest handler. Returned objects must satisfy outputSchema.

Backend pattern · requires matching operation declaration
import { defineExtension } from '@ambleloft/extension-sdk';
export const { activate } = defineExtension({
  activate(context) {
    context.subscriptions.push(
      context.operations.register('echo', async input => ({ text: input.text }))
    );
  }
});
Field / APIContract
OperationHandler(input: JsonObject, context: InvocationContext) → Promise<JsonObject>.
Disposabledispose(): void; use subscriptions for lifecycle cleanup.
extensionId / packageRevisionRead-only extension identity and package revision.

02InvocationContext

The host binds the invocation context; arbitrary input does not replace project, form or message identity.

Field / APIContract
requestId / callerRequest identifier; caller is page or agent.
projectId / signalOptional bound project; AbortSignal propagates cancellation.
form?flowInstanceId, stepId, submissionId, templateDigest, conversationId.
message?invocationId, messageId, actionId.
resourcesProjectResources for this invocation.
authentication.requestSession(resourceId)Interactive AuthenticationSession request, page calls only; declare timeoutMs: 120000 for login.

03ProjectResources

Project IDs must match the bound invocation project. Declared permissions still require runtime grants. Creating a conversation only creates a draft; it does not run the Agent.

Field / APIContract
getProject(projectId): Promise<Project>projects.read; returns id, name and description.
getProjectPath(projectId): Promise<string>projects.path.read; reads the project path.
createConversation({projectId,title,initialPrompt?})conversations.create; Promise<ConversationRef> with id, projectId and state.
openConversation(conversationId): Promise<void>conversations.open; page-only interactive opening, agent gets INTERACTION_REQUIRED.

04Configuration, storage and secrets

Declare the corresponding capabilities. KV revisions provide optimistic concurrency. null is create-only for absent keys, including after deletion; revisions remain monotonic.

Field / APIContract
storage.get(key): Promise<KvEntry | null>KvEntry = {value: Json, revision: number}.
storage.set(key,value,expectedRevision): Promise<number>expectedRevision: number or null; returns the new revision.
storage.delete(key,expectedRevision): Promise<void>Requires the current revision; reread on conflict.
configuration.get(): Promise<JsonObject>Read configuration; onDidChange(listener): Disposable observes changes.
secrets.get / set / deleteget(key): Promise<string|null>; set(key,value), delete(key): Promise<void>.
context.set(key,value): Promise<void>Value is boolean, string or number.
l10n.t(key,args?): stringargs: Record<string,string|number|boolean>; extension string localization.

05runtime-preview helpers

Preview capability · SDK 0.1.0-alpha.9

getResources(invocation) returns bound resources, rejects empty IDs and never creates conversations on open. observeConfiguration subscribes before reading to avoid stale initial data overwriting new events. It does not retry automatically.

@ambleloft/extension-sdk/runtime-preview · signatures
getResources(invocation: InvocationContext): ProjectResources;
observeConfiguration<T>(
  context: ExtensionContext,
  decode: (value: JsonObject) => T,
  onChange: (value: T) => void
): Disposable & { ready: Promise<void> };
Open the complete runnable sample

06Migrate to this internal contract

Preview capability · SDK 0.1.0-alpha.9

Install matching local SDK, CLI and core packages using the setup guide, with the matching host. Internal version 0.1.0-alpha.9 is not a formal release or platform certification. This contract drops five-method host compatibility: getMessages requires all seven methods and throws UNSUPPORTED if any is missing. Action records use id and effect; reportActionResult takes invocationId. A successful handler return still requires an explicit business-result report.

Prepare matching local packages

07Migrate model-tool and retry handling

user-input is a types-only entry: use import type. tools.schema.json and validate-input provide static validation; execution belongs to host model tools. Preserve full UI flow results and use the new ID after updates. Input creation retries return current state; mutation retries return the original receipt. Check answer and delivery separately. Job retries retain the original serialized request and key order; reconcile the original job on unknown. Handle operation Result, Node rejection, input Result and MCP isError separately without inventing error fields.

Run the minimal input example

08Run the supplied consumer checks

Run from the matching ambleloft-extension-samples root after the coordinator installs and verifies the same local package batch. The first command covers messages, page grants and cancellation, and CLI static positive/negative cases. The second checks types. Host doubles do not prove real authorization or desktop workflows. Then follow each capability guide in the matching host to check visible results and recovery. doctor still reports source matching only, with runtimeStatus=not-tested.

Code example
node --test verification/local-sdk/consumer.test.mjs verification/local-sdk/cli.test.cjs
node node_modules/typescript/bin/tsc -p verification/local-sdk/tsconfig.json
SDK / CLI 0.1.0-alpha.9 · Contract baseline Compatibility and preview notes · Sample source