Explorar documentación

Referencia del SDK de TypeScript de OOMOL

@oomol-lab/connector contiene tres clientes de TypeScript. Elige el cliente que coincida con la ruta del producto antes de usar la configuración compartida y la referencia de API de esta página:

  • Connector llama a cuentas conectadas a tu propia cuenta de OOMOL a través del gateway alojado.
  • ProjectConnector conecta y llama a cuentas propiedad de usuarios de tu producto SaaS.
  • OpenConnector llama a un entorno de ejecución de OpenConnector que tú operas.

Los clientes comparten el comportamiento de transporte, tipos precisos de acciones y el modelo de errores. Sus claves, límites de cuentas y métodos disponibles difieren.

El paquete es ligero y sin dependencias; el SDK construye cada solicitud y analiza la respuesta. TypeScript puede llamar a acciones como gmail.search_threads, slack.post_message y notion.append_block directamente.

Instalación

npm install @oomol-lab/connector   # or: bun add / pnpm add / yarn add

Requiere Node ≥ 18, para fetch y AbortController integrados. El SDK solo incluye dist, no tiene dependencias en tiempo de ejecución y es sideEffects: false, por lo que se puede tree-shake limpiamente. Usa Connector y ProjectConnector desde un entorno de ejecución de confianza del lado del servidor como Node, Bun, Deno o un edge worker. Las aplicaciones de navegador deben llamar a tu backend; nunca incluyas una clave de API personal o de Proyecto en el código del cliente.

Tres clientes de un vistazo

ConnectorProjectConnectorOpenConnector
AutenticaciónClave api_… personalClave oo_proj_… de ProyectoToken de entorno de ejecución opcional oct_…
Se conecta aGateway alojado por OOMOLGateway alojado por OOMOLUn entorno de ejecución de OpenConnector que tú operas
Recurso de cuentaConexiones personales o de EquipoCuentas conectadas para usuarios externosConexiones en el entorno de ejecución
Caso de usoLlamar a cuentas conectadas por un individuo o EquipoConectar y llamar a cuentas para usuarios de productos SaaSLlamar a un entorno de ejecución autoalojado
Guía de integraciónSDK de ConnectorProjectConnectorSDK de OpenConnector

Connector: llamar a conexiones personales o de Equipo

Obtener una clave de API

Necesitas una clave de API personal de OOMOL Connector, con el formato api_…. Crea una en OOMOL Console:

https://console.oomol.com/api-key

Establécela como variable de entorno. Esta guía usa OOMOL_API_KEY en todo momento. El gateway autoriza cada solicitud y recibe la clave como Authorization: Bearer <apiKey>.

Una clave api_… personal ejecuta acciones en conexiones personales o de Equipo. Para conectar cuentas para usuarios finales, usa una clave de Proyecto (oo_proj_…) y ProjectConnector; consulta la guía de integración de ProjectConnector. Para llamar a un entorno de ejecución autoalojado, usa su token de entorno de ejecución opcional (oct_…) y OpenConnector; consulta la guía del SDK de OpenConnector.

Inicio rápido

Construye un cliente y luego llama a una acción. Las dos formas a continuación son equivalentes.

import { Connector } from "@oomol-lab/connector";

const oomol = new Connector({ apiKey: process.env.OOMOL_API_KEY! });

// Path 1: dynamic string. Callable for any action id.
const { threads } = await oomol.execute("gmail.search_threads", { query: "from:boss" });

// Path 2: namespace sugar. Same call underneath.
const result = await oomol.gmail.search_threads({ query: "is:unread" });

execute devuelve la salida de la acción directamente. Cuando también quieras los metadatos de ejecución, usa executeRaw:

const raw = await oomol.executeRaw("gmail.search_threads", { query: "from:ceo" });
raw.data;        // the same value execute() returns
raw.executionId; // server-assigned execution id (useful for support / log correlation)
raw.actionId;    // echoed action id
raw.message;     // human-readable message from the success envelope

El flujo de llamada principal es execute y executeRaw.

Conceptos de Connector

El modelo del SDK tiene cinco conceptos principales. La autenticación, las credenciales y las llamadas al proveedor son gestionadas por el gateway:

TérminoQué es
GatewayEl servicio alojado de OOMOL Connector con el que habla este cliente. Contiene credenciales, realiza las llamadas reales al proveedor y devuelve un sobre uniforme. El SDK ejecuta ninguna lógica de integración localmente.
Proveedor / servicioUna API de terceros (gmail, slack, github, notion, …). Es el prefijo <service> de un id de acción.
AcciónUna operación en un proveedor, identificada como "<service>.<action>" (p. ej. gmail.search_threads). Las acciones son proporcionadas por el gateway y llamadas por el cliente.
ConexiónUna credencial almacenada y ya autorizada para un proveedor. Nunca tocas los tokens; nombras qué conexión usar mediante connectionName. OAuth y el ciclo de vida de las credenciales son responsabilidad del gateway.
EquipoAlcance de inquilino opcional, enviado como el encabezado x-oo-team-name.

El mismo vocabulario se traslada a la superficie del SDK: un id de acción es siempre "<service>.<action>", connectionName selecciona una conexión almacenada y, para el cliente de proyecto, externalUserId identifica a uno de tus usuarios finales.

Operaciones comunes

Quieres…UsaNotas
Ejecutar una acción modeladaexecute / executeRawLa línea tipada. executeRaw también devuelve { executionId, actionId, message }.
Acceder a un endpoint que aún no está modelado como acciónproxyPassthrough a la API ascendente, con las credenciales de la conexión inyectadas por el gateway.
Alimentar acciones a un LLM / crear formularios dinámicoscatalogJSON Schema en tiempo de ejecución (2020-12) para cualquier acción o proveedor.
Descubrir qué está conectadoapps.listLista de solo lectura de las conexiones que ya has enlazado.
Permitir que tus usuarios conecten sus cuentasProjectConnectorUn cliente separado, con alcance de proyecto, para conectar cuentas en nombre de tus usuarios finales y ejecutar acciones para ellos.

La cobertura de proveedores y acciones es proporcionada por el gateway. Actualmente admite más de 600 proveedores y sigue creciendo; descúbrela en tiempo de ejecución con oomol.catalog.providers().

Tipos precisos (opcional)

La ruta de cadena dinámica compila para cualquier actionId. De forma predeterminada, cada acción está tipada de forma flexible (Record<string, any> de entrada y salida), lo que mantiene las nuevas acciones invocables de inmediato. Para tipos precisos de entrada/salida por acción más JSDoc, instala el paquete de tipos complementario y añade una importación de efectos secundarios por proveedor que uses:

import { Connector } from "@oomol-lab/connector";
import "@oomol-lab/connector-types/gmail";   // precise types + JSDoc for gmail.*
import "@oomol-lab/connector-types/slack";   // …and slack.*

const oomol = new Connector({ apiKey: process.env.OOMOL_API_KEY! });

await oomol.gmail.search_threads({ query: "from:boss" }); // input + output now precise
await oomol.notion.append_block({ pageId, text });        // notion not imported → still loosely callable
npm install -D @oomol-lab/connector-types

Los tipos precisos provienen de @oomol-lab/connector-types y las importaciones de efectos secundarios, dejando el proyecto libre de archivos generados. Las acciones registradas obtienen autocompletado literal y tipos exactos de entrada/salida; las no registradas degradan a Record<string, any>. Cuando el paquete de tipos va por detrás del backend, las nuevas acciones siguen siendo invocables a través del fallback flexible. El entorno de ejecución principal y el paquete de tipos se publican por separado.

Requiere moduleResolution establecido en bundler, node16 o nodenext para que se resuelvan las importaciones de subruta (@oomol-lab/connector-types/gmail). Consulta el repositorio @oomol-lab/connector-types para detalles de configuración.

Configuración

Todos los campos excepto apiKey son opcionales:

new Connector({
  apiKey: process.env.OOMOL_API_KEY!,        // required
  baseUrl: "https://connector.oomol.com/v1", // default
  team: "acme",                              // default team → x-oo-team-name
  connectionName: "work",                    // default connection (prefer per-call / using())
  timeoutMs: 30_000,                         // default per-request timeout
  maxRetries: 2,                             // default; retries 429 / 5xx / network with backoff + jitter
  fetch: customFetch,                        // inject for tests / proxies / tracing
});
CampoPredeterminadoNotas
apiKeyObligatorio. Se envía como Authorization: Bearer <apiKey>.
baseUrlhttps://connector.oomol.com/v1Anúlalo explícitamente en la configuración del cliente.
teamBajo qué inquilino se ejecuta la llamada.
connectionNameQué conexión almacenada usar cuando un proveedor tiene más de una. Úsalo como valor predeterminado del cliente para configuraciones simples; para varias conexiones, establécelo por llamada o mediante using().
timeoutMs30_000Tiempo de espera por solicitud en milisegundos.
maxRetries2Reintentos en 429 / 5xx / errores de red, con retroceso exponencial y jitter.
fetchfetch globalInyecta un fetch personalizado para pruebas, agentes de proxy o trazabilidad.

Para acciones con efectos secundarios, como gmail.send_email o slack.post_message, pasa { retries: 0 } a menos que esa acción proporcione un mecanismo de idempotencia que hayas verificado. Puede ocurrir un fallo de red después de que el proveedor haya aceptado la solicitud, por lo que un reintento automático puede repetir la operación.

Ámbitos y opciones por llamada

Tres capas se resuelven en este orden de precedencia: opciones por llamada > ámbito de using() > valores predeterminados del cliente.

using() devuelve un subcliente con ámbito inmutable que combina los valores predeterminados dados; el cliente original no se modifica:

const work = oomol.using({ connectionName: "work", team: "acme" });
await work.gmail.search_threads({ query: "label:urgent" }); // runs under "work" / "acme"

Las opciones por llamada se aplican solo a esa llamada y tienen la mayor precedencia:

await oomol.execute(
  "gmail.search_threads",
  { query: "from:ceo" },
  {
    team: "acme",           // override team for this call
    connectionName: "alt",  // pick a different connection for this call
    timeoutMs: 10_000,      // tighter timeout for this call
    retries: 0,             // disable retries for this call
    signal: controller.signal, // forward an AbortSignal
  },
);

connectionName se resuelve con la misma estratificación. Se transporta en la red como el encabezado x-oo-connector-alias (el nombre del campo de la puerta de enlace es alias); la superficie del SDK usa connectionName.

Proxy: llamar directamente a un endpoint ascendente

proxy llama directamente a un endpoint de API ascendente. La puerta de enlace inyecta credenciales de la conexión seleccionada, mientras que la solicitud y la respuesta mantienen la forma de la API ascendente.

// Typed GET. The request path uses the `endpoint` field.
const repos = await oomol.proxy<Array<{ name: string }>>("github", {
  endpoint: "/user/repos",
  method: "GET",
  query: { per_page: 5, sort: "updated" },
});
repos.status;               // upstream HTTP status
repos.data.map((r) => r.name);

// POST with a body and upstream headers; these headers go to the provider.
await oomol.proxy("github", {
  endpoint: "/repos/acme/widgets/issues",
  method: "POST",
  headers: { "X-GitHub-Api-Version": "2022-11-28" },
  body: { title: "Tracking issue", labels: ["chore"] },
});

endpoint acepta una ruta (resuelta contra la URL base del proveedor) o una URL completa, lo cual es útil para proveedores con hosts regionales como https://eu.posthog.com/api/.... method es uno de GET | POST | PUT | PATCH | DELETE. La respuesta es { status, headers, data }. El cuerpo del proxy es estricto en el backend: las claves de nivel superior desconocidas se rechazan como invalid_input.

Catálogo: inspeccionar proveedores y acciones

El catálogo proporciona metadatos de tiempo de ejecución de solo lectura para formularios dinámicos, validación y definiciones de herramientas de LLM. Los esquemas de entrada/salida usan JSON Schema (2020-12) y son independientes del paquete de tipos en tiempo de compilación.

// List providers; optionally narrow server-side.
const all = await oomol.catalog.providers();                       // every provider
const mailish = await oomol.catalog.providers({ q: "mail" });      // free-text search → ?q=
const some = await oomol.catalog.providers({ service: ["gmail", "slack"] }); // restrict → ?service=…

// All actions of one service.
const actions = await oomol.catalog.actions("gmail");

// Full metadata for one action, including runtime JSON Schema.
const meta = await oomol.catalog.action("gmail.search_threads");
meta.name;          // human-readable name
meta.requiredScopes;// OAuth scopes the action needs
meta.inputSchema;   // JSON Schema (2020-12) for the input
meta.outputSchema;  // JSON Schema (2020-12) for the output

Cada proveedor incluye { service, displayName, iconUrl, homepageUrl, categories, authTypes }.

Apps: enumera tus cuentas conectadas

apps.list() devuelve una vista de solo lectura de las conexiones que la puerta de enlace ya tiene para ti. La creación y eliminación de conexiones se realiza en Console.

const apps = await oomol.apps.list();
for (const app of apps) {
  // { id, service, status, connectionName, … }; connectionName is null when none is set.
  console.log(`${app.service}: id=${app.id} status=${app.status} connectionName=${app.connectionName}`);
}

// Target a specific connection by passing its connectionName back as the per-call selector.
const work = apps.find((a) => a.connectionName === "work");
if (work) {
  await oomol.execute("gmail.search_threads", { query: "is:unread" }, { connectionName: "work" });
}

Manejo de errores

Los fallos lanzan un ConnectorError tipado. La cancelación por parte del llamador (un AbortSignal abortado) rechaza con el AbortError estándar, por lo que se puede manejar por separado de los errores de la puerta de enlace o de transporte.

import { Connector, ConnectorError, isRetryable } from "@oomol-lab/connector";

try {
  await oomol.slack.post_message({ channel: "#general", text: "shipped" });
} catch (err) {
  if (err instanceof ConnectorError) {
    err.code;        // discriminable union, e.g. "rate_limited", "credential_expired"
    err.status;      // HTTP status (0 for client-side / network errors)
    err.requestId;   // failure-correlation id
    err.actionId;    // when applicable
    err.executionId; // when applicable
    err.data;        // upstream response body, e.g. on provider_error
    if (isRetryable(err)) {
      // 429 / 5xx / network / rate_limited / proxy_upstream_timeout / request_in_progress
    }
  } else {
    throw err; // non-ConnectorError, e.g. AbortError from caller cancellation; rethrow
  }
}

err.code es una unión abierta: los códigos de backend conocidos obtienen autocompletado, y los nuevos códigos de backend siguen pasando como cadenas. Mantén una rama predeterminada al manejarla. Códigos comunes, agrupados:

GrupoCódigos
Entrada / solicitudinvalid_input, invalid_request_payload, invalid_request_signature
App / proveedorapp_not_found, app_not_ready, app_auth_type_mismatch, provider_not_found, provider_not_configured, provider_config_not_found, provider_error, profile_not_found
Credencial / autenticacióncredential_expired, scope_missing, user_oauth_client_required
Selección de conexiónconnection_ambiguous, connection_account_conflict, connection_alias_conflict, connection_request_not_found, connected_account_not_found
Proxyproxy_not_supported, proxy_upstream_error, proxy_upstream_timeout, proxy_response_too_large
Tasa / concurrenciarate_limited, request_in_progress, request_key_conflict, request_key_used
Solo cliente (estado 0, sin solicitud enviada o fallo de transporte)client_invalid_request, client_timeout, client_network_error, client_wait_timeout

isRetryable(err) devuelve true para rate_limited, proxy_upstream_timeout, request_in_progress, HTTP 429, cualquier 5xx y fallos de transporte (estado 0). Devuelve false para errores de validación del cliente (client_invalid_request) y el límite de waitForConnection (client_wait_timeout); esos casos suelen requerir un cambio de llamada o de flujo de espera.

Cancelación y tiempos de espera

Reenvía un AbortSignal para cancelar; establece timeoutMs para limitar una sola llamada. La capa de reintentos integrada maneja fallos transitorios. Usa retries: 0 para un único intento determinista.

const controller = new AbortController();
setTimeout(() => controller.abort(), 50);
try {
  await oomol.execute("gmail.search_threads", { query: "huge" }, { signal: controller.signal });
} catch (err) {
  (err as Error).name; // "AbortError"
}

ProjectConnector: conecta cuentas para los usuarios del producto

Connector ejecuta acciones sobre tus propias conexiones. ProjectConnector es para productos SaaS: tus usuarios finales vinculan sus propias cuentas de Gmail / Slack / GitHub / … a través de tu app, y tu backend ejecuta acciones en su nombre. Este es el modelo de autenticación gestionada que usan productos como Composio y Pipedream Connect.

Con OAuth, el usuario autoriza en una página alojada por el gateway; los tokens del proveedor permanecen en el gateway y tu código maneja identificadores opacos. project.connect.apiKey y project.connect.customCredential son diferentes: tu backend de confianza recibe el secreto del usuario y lo envía al gateway. Mantén esos secretos fuera de navegadores, prompts, contexto del modelo y logs.

El identificador de usuario final

externalUserId es la clave de aislamiento de usuario para el cliente de proyecto. Tú la eliges, normalmente desde tu propia base de datos de usuarios. Las operaciones del proyecto, como conectar una cuenta, esperar una conexión y ejecutar una acción, están limitadas a ella. Pasa el mismo externalUserId de forma consistente y el gateway mantiene aisladas las conexiones de cada usuario.

Construir el cliente de proyecto

ProjectConnector es un cliente independiente que se construye con una Project API key (oo_proj_…). Proporciona operaciones con alcance de proyecto como connect.*, waitForConnection, getUserProfile, execute, executeRaw y forUser.

import { ProjectConnector } from "@oomol-lab/connector";

const project = new ProjectConnector({ apiKey: process.env.OOMOL_PROJECT_API_KEY! }); // oo_proj_...

La configuración en Console va primero. Antes de que tu backend conecte cuentas, un administrador crea un Project, una configuración de proveedor y una Project API key en OOMOL Console. La configuración inicial y el flujo REST de backend correspondiente se cubren en la guía de Connector for SaaS. Este SDK es el wrapper tipado sobre la misma API en tiempo de ejecución.

OAuth: crear un enlace y esperar a que se complete

OAuth tiene dos pasos: crear una solicitud de conexión pendiente, enviar al usuario a autorizar, y luego esperar a que se complete.

// 1. Create a pending connection request for one of your users.
const request = await project.connect.oauth("user_42", {
  service: "gmail",
  connectionName: "work",                          // the name to assign; reuse it later to target this account
  returnUri: "https://app.example.com/connected",  // where the gateway returns the user after the callback
});

// 2. Send your user to the provider's authorization page.
redirectUserTo(request.authorizationUrl);

// 3. Poll until the user finishes (or it fails / expires). Returns the final connection request.
const connected = await project.waitForConnection(request);
connected.status;             // "connected" | "failed" | "expired"
connected.connectedAccountId; // the stored account id once connected

El authorizationUrl primero abre una página de entrada alojada por Connector que indica tu proyecto y el proveedor que el usuario está a punto de autorizar, y luego envía al usuario a la página de OAuth del proveedor.

Entrada de autorización de Connector mostrando my-saas conectando con Gmail antes de redirigir a Gmail

waitForConnection consulta hasta que la solicitud sale del estado initiated y lo devuelve. Si el usuario no completa la autorización, la solicitud pasa naturalmente a expired. Si maxWaitMs (por defecto 600_000ms, coincidiendo con la expiración de la solicitud) transcurre primero, lanza un ConnectorError con código client_wait_timeout; un signal abortado rechaza con el AbortError estándar.

Cuando se alcanza tu returnUri, el gateway añade parámetros de consulta que puedes leer en tu página de callback:

status=success
service=gmail
providerConfigId=pc-1
externalUserId=user_42
connectedAccountId=ca-1

…o, en caso de cancelación / error del proveedor:

status=error
code=<connector-error-code>
message=<human-readable-message>

API key / credencial personalizada: síncrono

Las conexiones por API key y credencial personalizada devuelven una cuenta inmediatamente. Solo OAuth necesita waitForConnection.

// The end user's own upstream key (e.g. an OpenAI sk-…), not your oo_proj_ key.
const account = await project.connect.apiKey("user_42", { service: "openai", apiKey: "sk-..." });
account.available; // whether the account can execute actions right now

// Provider-specific credential fields, validated by the gateway against the provider config.
await project.connect.customCredential("user_42", {
  service: "jira",
  values: { email: "user@acme.com", token: "..." },
});

Cada llamada a connect.* identifica el proveedor por exactamente uno de service o providerConfigId. Usa providerConfigId cuando un proyecto tenga más de una configuración para el mismo servicio; service es el caso simple.

¿Como quién se conectaron?

getUserProfile lee el titular de la cuenta de terceros detrás de una cuenta conectada: quién es realmente tu usuario final en el proveedor. El gateway lo obtiene en vivo del proveedor y lo normaliza en una única forma entre proveedores.

const { service, profile, fetchedAt } = await project.getUserProfile(account.connectedAccountId);

profile.id;          // stable provider-side user id
profile.kind;        // "user" | "bot" | "service_account" | "unknown" (open union)
profile.username;    // handle, or null
profile.displayName; // display name, or null
profile.avatarUrl;   // avatar URL, or null
profile.email;       // email, or null when the granted scopes do not expose it
profile.metadata;    // provider-specific fields the gateway exposes

Los campos que un proveedor omite o que los scopes concedidos no cubren (email con mayor frecuencia) permanecen presentes en la respuesta con un valor null. fetchedAt es la marca de tiempo Unix en milisegundos en la que el gateway leyó el perfil. Pasa un connectedAccountId de un resultado connect.apiKey / connect.customCredential, o de un ConnectionRequest que alcanzó connected. Un id desconocido rechaza con connected_account_not_found; un proveedor que carece de la capacidad userProfile rechaza con profile_not_found; una cuenta inactiva o inutilizable puede rechazar con app_not_ready, app_auth_type_mismatch o credential_expired. El subcliente con alcance también lo tiene: user.getUserProfile(connectedAccountId).

Ejecutar en nombre del usuario

// The provider service is derived from the actionId prefix ("gmail").
// Without connectionName / connectedAccountId, the user's latest active account is used.
const out = await project.execute(
  "user_42",
  "gmail.search_threads",
  { query: "is:unread" },
  { connectionName: "work" },
);

Precedencia de selección de cuenta: connectedAccountId (una cuenta específica) tiene prioridad sobre connectionName (una cuenta por su nombre); sin ninguno de los dos, el gateway usa la última cuenta activa del usuario para ese proveedor. project.executeRaw devuelve el mismo sobre { data, executionId, actionId, message } que el cliente personal.

Limitar el alcance a un usuario

forUser vincula el externalUserId una vez para que las llamadas posteriores no repitan el id:

const user = project.forUser("user_42");
const request = await user.connect.oauth({ service: "slack" });
const slack = await user.waitForConnection(request);
if (slack.status === "connected") {
  await user.execute(
    "slack.post_message",
    { channel: "#general", text: "shipped" },
    { connectedAccountId: slack.connectedAccountId },
  );
}

project.execute reutiliza el mismo registro @oomol-lab/connector-types que la ruta personal: los proveedores importados obtienen entradas/salidas precisas, y el resto permanece invocable de forma flexible.

Ciclo de vida de la solicitud de autorización y la cuenta

ObjetoCuándo lo obtienesCampos clave
ConnectionRequestdevuelto por connect.oauth, releído mediante getConnectionRequest / waitForConnectionid, status (initiatedconnected / failed / expired), authorizationUrl, connectedAccountId, externalUserId, connectionName, expiresAt
ConnectedAccountdevuelto de forma síncrona por connect.apiKey / connect.customCredential; señalado por una solicitud OAuth completadaid / connectedAccountId, status (active, reauth_required, error, disconnected), available, externalUserId, connectionName, service

available es true solo cuando todo lo necesario para ejecutar está en su sitio: la configuración del proveedor está activa, la cuenta está activa, la app subyacente está activa y existe una credencial. Ambos campos de estado son uniones abiertas; mantén una rama por defecto para gestionar nuevos estados del backend.

¿Vienes de Composio / Pipedream?

Composio / Pipedream@oomol-lab/connector
userId / external_user_idexternalUserId
connectedAccounts.initiate / createConnectToken (OAuth)project.connect.oauth
connectedAccounts.initiate + AuthScheme.APIKeyproject.connect.apiKey
waitForConnection()project.waitForConnection()
tools.execute(slug, { userId, arguments })project.execute(externalUserId, actionId, input)
composio.getEntity(userId)project.forUser(externalUserId)

OpenConnector: llamar a un runtime autoalojado

¿Ejecutas el servidor Connector de código abierto por tu cuenta — en localhost, en Docker o en tu propia infraestructura? OpenConnector es el cliente personal para ello. Refleja la superficie de Connector (ambas rutas de llamada, proxy, catalog, apps) apuntando al servidor que ejecutas, por lo que el código que ya escribiste apenas cambia. Poner en marcha el servidor es un tema aparte — consulta la guía de autoalojamiento de OpenConnector.

El cliente OpenConnector apunta a un runtime que tú operas. La configuración de ese runtime determina la organización de cuentas, la selección de conexiones y la política de acceso.

import { OpenConnector } from "@oomol-lab/connector";

const open = new OpenConnector(); // local/private setup only; defaults to http://localhost:3000

await open.execute("hackernews.get_top_stories", {});             // path 1 — dynamic string
await open.gmail.search_threads({ query: "from:boss" });          // path 2 — namespace sugar, same registry types
await open.proxy("github", { endpoint: "/user", method: "GET" }); // path 3 — passthrough to an un-modeled endpoint
await open.catalog.search("send email", { limit: 5 });            // catalog extras: search, services
await open.apps.list();                                           // read-only view of the runtime's connections

Ambas rutas de llamada y el flujo de tipos precisos coinciden con el Connector personal; se aplican las mismas importaciones de efectos secundarios de @oomol-lab/connector-types. OpenConnector acepta una ruta relativa que comienza con / para proxy.endpoint; una URL absoluta devuelve invalid_input. Un proveedor al que le falta un ejecutor de proxy devuelve proxy_not_supported.

Apúntalo a tu servidor

baseUrl acepta el origen del servidor, y el cliente añade el prefijo de ruta de la API. Un runtime sin tokens solo es adecuado para localhost o una red que de otro modo sea privada. Antes de exponerlo a través de una URL pública, crea un token de runtime (oct_…) en la Web Console bajo Access y exígelo a todos los clientes /v1 y /mcp.

const open = new OpenConnector({
  baseUrl: "https://connect.internal.example.com",       // the server origin
  runtimeToken: process.env.OOMOL_CONNECT_RUNTIME_TOKEN!, // oct_…; required for a public runtime
  connectionName: "work",                                // optional client-level default connection
});

Todos los campos son opcionales. timeoutMs, maxRetries y fetch se comportan exactamente igual que en el cliente alojado.

Superficie específica del runtime

OpenConnector proporciona estos métodos específicos del runtime:

await open.health();                                    // { ok, runtime } — connectivity / auth probe
await open.catalog.services();                          // every service id that has actions
await open.catalog.search("top stories", { limit: 3 }); // rank actions by free-text relevance
await open.apps.listByService("github");                // one service's connections
await open.apps.authenticated(["github", "notion"]);    // which have a REAL credential stored

La selección de conexiones tiene dos capas: un connectionName por llamada anula el valor predeterminado a nivel de cliente, y omitir ambos selecciona la conexión "default" del runtime.

Usa la Web Console para la gestión. Crea conexiones, configura clientes OAuth y acuña tokens de runtime en la consola; el SDK OpenConnector llama al runtime configurado. Consulta la guía de autoalojamiento para la configuración. Cuando un id de servicio colisiona con un nombre de miembro (execute / executeRaw / health / proxy / catalog / apps), llámalo a través de execute("<service>.<action>", …).

Recorrido completo ejecutable — examples/open.ts.

Referencia

Connector (clave api_… personal)

new Connector(config: ClientConfig)

oomol.execute(actionId, input, options?)     // → action output
oomol.executeRaw(actionId, input, options?)  // → { data, executionId, actionId, message }
oomol.<service>.<action>(input, options?)    // namespace sugar for execute
oomol.using(scope)                           // → immutable scoped sub-client
oomol.proxy(service, { endpoint, method, query?, headers?, body? }, options?) // → { status, headers, data }
oomol.catalog.action(actionId, options?)     // → ActionMetadata
oomol.catalog.actions(service, options?)     // → ActionMetadata[]
oomol.catalog.providers(query?, options?)    // → ProviderMetadata[]   query: { service?: string[]; q?: string }
oomol.apps.list(options?)                    // → ConnectedApp[]

ProjectConnector (clave oo_proj_… del proyecto)

new ProjectConnector(config: ProjectConnectorConfig)

project.connect.oauth(externalUserId, input, options?)            // → ConnectionRequest (pending)
project.connect.apiKey(externalUserId, input, options?)           // → ConnectedAccount (synchronous)
project.connect.customCredential(externalUserId, input, options?) // → ConnectedAccount (synchronous)
project.getConnectionRequest(connectionRequestId, options?)       // → ConnectionRequest
project.waitForConnection(requestOrId, options?)                  // → ConnectionRequest   options: { pollIntervalMs?, maxWaitMs?, signal?, timeoutMs? }
project.getUserProfile(connectedAccountId, options?)              // → ConnectedAccountProfile
project.execute(externalUserId, actionId, input, options?)        // → action output
project.executeRaw(externalUserId, actionId, input, options?)     // → { data, executionId, actionId, message }
project.forUser(externalUserId)                                   // → ProjectUser (same methods, id bound)

La entrada de connect.* es { service | providerConfigId } & { connectionName?, … } (exactamente uno de service / providerConfigId). Las opciones de execute añaden { providerConfigId?, service?, connectedAccountId?, connectionName? }.

OpenConnector (runtime autoalojado, token oct_… opcional)

new OpenConnector(config?: OpenConnectorConfig)   // every field optional; baseUrl defaults to http://localhost:3000

open.execute(actionId, input, options?)       // → action output
open.executeRaw(actionId, input, options?)    // → { data, executionId, actionId, message }
open.<service>.<action>(input, options?)      // namespace sugar for execute
open.health(options?)                         // → { ok, runtime }
open.proxy(service, { endpoint, method, query?, headers?, body? }, options?) // → { status, headers, data }   (endpoint must be a relative path)
open.catalog.action(actionId, options?)       // → OpenActionMetadata
open.catalog.actions(service, options?)       // → OpenActionMetadata[]
open.catalog.services(options?)               // → string[]   (service ids that have actions)
open.catalog.providers(query?, options?)      // → ProviderMetadata[]
open.catalog.search(q, query?, options?)      // → OpenActionSearchResult[]   query: { service?, limit? }
open.apps.list(options?)                      // → ConnectedApp[]
open.apps.listByService(service, options?)    // → ConnectedApp[]
open.apps.authenticated(services, options?)   // → string[]   (services with a real credential)

options es { connectionName?, signal?, timeoutMs?, retries? } (sin team, sin using()). config añade { baseUrl?, runtimeToken?, connectionName?, timeoutMs?, maxRetries?, fetch? }.

Exportaciones

import {
  Connector,
  ProjectConnector,
  OpenConnector,
  ConnectorError,
  isRetryable,
} from "@oomol-lab/connector";
import type {
  ClientConfig, CallOptions, ScopeOptions, RawResult,
  ProxyRequest, ProxyResponse, ProxyMethod,
  CatalogApi, ActionMetadata, ProviderMetadata, ProviderQuery,
  AppsApi, ConnectedApp,
  ConnectorErrorCode,
  ProjectConnectorConfig, ProjectCallOptions, ProjectExecuteOptions,
  ConnectionRequest, ConnectedAccount, ProviderSelector,
  ConnectedAccountProfile, ProviderUserProfile, ProviderUserKind,
  OAuthConnectInput, ApiKeyConnectInput, CustomCredentialConnectInput,
  OpenConnectorConfig, OpenConnectorApi, OpenCallOptions, OpenExecuteOptions,
  OpenCatalogApi, OpenAppsApi, OpenHealth,
  OpenActionMetadata, OpenActionFollowUp, OpenActionAsyncLifecycle,
  OpenActionSearchResult, OpenSearchQuery,
} from "@oomol-lab/connector";

En el repositorio hay ejemplos ejecutables y verificados de tipos en el directorio examples/.

Licencia

MIT, consulta el repositorio connector-sdk.