@original-land/original-connect
v0.3.0
Published
Original Connect SDK — OAuth 2.1 / OIDC client for the Original AI ecosystem (login, chat, connectWorkspace).
Readme
@original-land/original-connect
Framework-agnostic TypeScript SDK for Original Connect — the OAuth 2.1 / OpenID Connect identity layer for the Original AI ecosystem. Log users in, chat with agents (including the shared Dana agent), and connect a workspace MCP — without ever exposing API keys to the user.
Install
npm install @original-land/original-connect
# or: pnpm add @original-land/original-connectThis is a public package on the npm registry (registry.npmjs.org) — no authentication or .npmrc is required to install it. Anyone can use it.
Subpath exports
| Import | Use | Contents |
|---|---|---|
| @original-land/original-connect | any runtime | types, PKCE utils, URL builders, /.well-known discovery, error types, scopes |
| @original-land/original-connect/server | confidential (has a backend) | createConfidentialClient → getAuthorizeUrl, exchangeCode, refresh, connectWorkspace |
| @original-land/original-connect/browser | public / PKCE (browser-only) | createBrowserClient → login, handleCallback, getChatToken, chat |
Server (confidential)
import { createConfidentialClient } from '@original-land/original-connect/server';
import { Scopes, agentChatScope, buildScope } from '@original-land/original-connect';
const oa = createConfidentialClient({ clientId, clientSecret, redirectUri, issuer });
const url = await oa.getAuthorizeUrl({
scope: buildScope([Scopes.profile, Scopes.workspace, agentChatScope(danaBotId)]),
state,
});
const tok = await oa.exchangeCode(code); // { accessToken, refreshToken, ... }
await oa.connectWorkspace(tok.accessToken, { mcpUrl, apiKey, scope: Scopes.workspace }); // push per-user keyConfidential clients receive an access token (~1h) + rotating refresh token, both kept on the backend.
Browser (public / PKCE)
import { createBrowserClient } from '@original-land/original-connect/browser';
import { agentChatScope } from '@original-land/original-connect';
const oa = createBrowserClient({ clientId, redirectUri, issuer, chatApiUrl });
oa.login({ scope: agentChatScope(botId) }); // first-party redirect; PKCE verifier stored in sessionStorage
const tok = await oa.handleCallback(); // exchanges code using the PKCE verifier
await oa.getChatToken(); // returns a valid short-lived chat token (refreshes when possible)
const reply = await oa.chat(botId, message); // calls the chat backend with Authorization: BearerPublic/PKCE clients receive only a short-lived chat token (5–15 min). No client secret and no persistent refresh token ever live in the browser; the MCP/workspace key never reaches the client.
Scopes
openid, profile, agent.chat:<botId> (use agentChatScope(botId)), workspace, agent.purchase.
Token shapes
- Confidential: access token (~1h) + rotating refresh token (backend only).
- Public/PKCE: short-lived chat token only; refreshed silently / via in-memory rotation. No persistent browser refresh token.
Agent-integration prompts
Ready-to-paste prompts for coding agents live in prompts/: Dana confidential backend, public PKCE static page, purchasable agent, bring-your-own-agent. Each warns never to expose secrets client-side.
Development
pnpm install
pnpm test # vitest
pnpm typecheck
pnpm build # tsup → dist (ESM + CJS + d.ts)Every client call goes through an injectable fetch, so the SDK is fully unit-testable in isolation against the documented HTTP contracts (no live issuer required).
