@byokit/connect

中文文档
0.8.1发布于 2026/10/25Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 2067

TypeScript套件让人们通过他们已经支付的人工智能计划,在网络,电话和桌面上登录到你的应用程序.

中文使用文档
文档目录15 节
  1. 仅测试端点覆盖
  2. 使用应用程序提供的定向签名
  3. 房子谷歌客户端
  4. 检查应用程序细节并检查补助金使用寿命
  5. 用设备代码连接 GitHub
  6. 在电脑上循环
  7. 完整的 MCP 客户端
  8. 列出要连接的应用程序
  9. 读取和搜索 Gmail
  10. 发送Gmail, 每封信一次批准
  11. 所有者入境的历史和出口
  12. 刷新、出错和存储
  13. 密封桌面令牌存储
  14. 船员领养
  15. 核查

@ byokit/ 连接

连接一个人的在线文件,邮件,日历,笔记,设计,代码或其他远程账户. 签名打开提供者自己的页面. 证书留在键盘上 传球 瞄准装置上的那个人 没有账户池,代理, 环境认证查询、记录或额外选择切换.

npm install @byokit/connect

主要导出为可移植到Node,Electron,浏览器和PWA. 这需要 fetch, (中文(简体) ), 网络加密, btoa,以及 URL API; 本地主机必须先提供这些全局 导入它。 可选 /node 导出只拥有回回调监听器. 主条目对节点或密钥后端没有运行时间依赖.

仅测试端点覆盖

仅针对当地融合测试, ConnectOptions.endpoints 接受完整的提供者 URL;省略的值使用生产终点. 例如,模拟0.12.2服务于谷歌授权 http://localhost:4000/o/oauth2/v2/auth符号 http://localhost:4000/oauth2/token,并使用 Gmail API 基础 http://localhost:4000/gmail/v1。通过相同的 endpoints 对象 MailReader 或者说 MailSender ,以路由 Gmail 调用其 Google API . Connection.apiBase 曝光配置的供應器自動呼叫的API Base; 套件本身不做GitHub REST API呼叫. GitHub 设备代码和令牌 URL 对于本地设备流服务器来说可以被覆盖,因为模拟 01.2.2 不执行这些路线.

使用应用程序提供的定向签名

import { connect } from '@byokit/connect';
import type { Keystore } from '@byokit/secrets';

// Supply your app's store, scoped to this person on this device.
declare const store: Keystore;
const drive = connect('drive', {
  store,
  person: 'Umer',
  redirectUri: 'https://your-app.example/connect/callback',
  client: { id: 'your-google-client-id', secret: 'your-google-client-secret' },
});

const flow = await drive.signIn();
// Open flow.url in the host's browser/auth session.
// Route its complete callback URL to the same flow instance:
await flow.finish('https://your-app.example/connect/callback?state=...&code=...');

const accessToken = await drive.token(); // Trusted API calls only; never show/log it.
await drive.disconnect();

connect(target, options) 创建一个手柄. signIn() 返回时 { url, redirectUri, finish, cancel }调用 cancel() 当关闭登录表时。 呼吁 connected(), (中文(简体) ), token() 财务报告和审定财务报表 disconnect() 重建手柄后的工作 拥有同一商店,个人,目标及配置的客户端ID. 重定向端口 可以在不丢失已保存的连接的情况下更改。 更新的登录将取消 更古老的流量;回调有15分钟的期限,只能使用一次.

Google要求主机注册客户端. 使用有回回路的桌面客户端, 或为该客户端登记精确的 HTTPS/内置重定向。 预设保留谷歌 离线/ 同意参数并请求一次服务 : google (身份), drive (单位:千美元)drive.file, (中文(简体) ), gmail (只读;通过) scopes 发送)和 calendar (活动). 主机拥有 Google同意-屏幕发布和API授权. 包里没有探测器 无文件提供者网页或强制实行产品专用审批政策.

notion, (中文(简体) ), canva 和任意 HTTPS MCP URL 发现其保护资源 元数据、授权服务器和动态注册端点。 如果服务器 不提供注册,通过注册的应用程序 client自定义 Provider 对象可以提供 oauth 结束点, a issuer、范围和额外授权 参数。 选项 scopes 覆盖预设/发现的范围; 安全 参数(state, PKCE, 响应类型, 客户端和重定向) 无法覆盖 结束 extra。没有保存明显不完整的授予范围的登录.

房子谷歌客户端

一个Google OAuth客户端服务于该馆运行的每条Google路线: 此工具包的Gmail 读者和发送者,以及Crewhouse的谷歌连接.

  • 客户端 : 类型 桌面应用程序在房子的谷歌云项目中 Gmail, 日历和驱动 API 启用 。 桌面客户端接受任何回回端口, 所以 connectLoopback 不需要重定向注册.
  • 同意: 外部出版(生产· ; 测试 赠款停止 7天之后). 同意筛选清单 gmail.readonly, (中文(简体) ), gmail.send, (中文(简体) ), calendar.events 财务报告和审定财务报表 drive.file。每个连接仍然需要一种服务; 发送添加 gmail.send 结束 scopes。 。 。 .
  • 秘诀 : jSON Google提供下载,未作改动,地点: ~/.config/byokit/google-oauth-client.json,模式600。 从未在寄存器, 日志 或测试家.
import { homedir } from 'node:os';
import { join } from 'node:path';
import { connectLoopback, googleClientFile } from '@byokit/connect/node';
import type { Keystore } from '@byokit/secrets';

declare const store: Keystore;
declare const yourApp: { openExternal(url: string): Promise<void>; setUpGoogle(): never };

const client = await googleClientFile(join(homedir(), '.config', 'byokit', 'google-oauth-client.json'));
if (!client) yourApp.setUpGoogle(); // No file yet: Google is not set up on this computer.
const attempt = await connectLoopback('gmail', { store, person: 'Umer', client,
  scopes: ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/gmail.send'],
  open: url => yourApp.openExternal(url) });
await attempt.done; // Then MailReader/MailSender on attempt.connection.

googleClientFile(path) 仅读取主机通过的道路。 它回来了 null 何时 文件缺席, 拒绝其它用户可以读取的文件, 非常规文件 路径, 或除桌面应用程序以外的任何客户端类型, 并带有纯信息 绝不重复文件的内容.

检查应用程序细节并检查补助金使用寿命

import type { Connection } from '@byokit/connect';

declare const drive: Connection;
declare const enteredClientId: string;
declare const enteredClientSecret: string;

const check = await drive.verifyClient(); // Uses options.client.
// Or check newly entered details without changing the saved connection:
const entered = await drive.verifyClient({ id: enteredClientId, secret: enteredClientSecret });
const grant = await drive.grant(); // Trusted app code only; contains credentials.

grant() 返回快照或 null 也不给任何供货商打电话。 时间是Unix 毫秒长. refreshTokenExpiresIn 保存提供者的 refresh_token_expires_in 秒数; refreshTokenExpiresAt 绝对期限. 签名/重新答复计算收到时的截止日期,省略刷新 寿命字段保留上一个最后期限。 需要过期的更新补助金 登录而不发送另一个刷新请求.

verifyClient(client?) 使用选中的符号端点,并刻意使用 无需阅读或更改个人补助金。 对于 Google, (英语), invalid_client 产量 outcome: 'invalid'; a 400 (韩语) invalid_grant 产量 'valid'; 网络故障和所有其他回复均产生 'inconclusive'每一个 结果包括平原 message; 失败的提供者回复可能包含同样内容 消毒诊断 cause 作为 ConnectError需要保密。 这个检查 只有客户端认证; 它不检查同意-屏幕发布, 启用 API,重定向注册或范围. 测试只使用被注入的假终点.

用设备代码连接 GitHub

import { connect, deviceSignIn } from '@byokit/connect';
import type { Keystore } from '@byokit/secrets';

declare const store: Keystore;
const options = { store, person: 'Umer', client: { id: 'your-github-oauth-app-client-id' }, scopes: ['repo'] };
const flow = await deviceSignIn('github', options);
// Show flow.userCode and flow.verificationUri (github.com/login/device);
// the person types the code there on any device.
await flow.finish(); // Resolves once they approve; call flow.cancel() when the sheet closes.

const github = connect('github', options);
await github.connected(); // true

deviceSignIn(provider, options) 启动 RFC 8628 设备签名并返回 { userCode, verificationUri, expiresAt, finish, cancel }· ; expiresAt 是 Unix 时 毫秒长. 它需要应用自己的OAuth客户端ID,并启用设备流; 没有房子 GitHub 客户端,没有 redirectUri。 。 。 . finish() 民意调查 提供者的间隔, 增加5秒 slow_down,并不断等待 通过一个 民意调查无法通过。 只有经批准的密码才能储存一笔赠款 密钥记录 connect() 读取,所以 connected(), (中文(简体) ), grant() 财务报告和审定财务报表 token() 之后工作时。 过期的代码拒绝方式 ConnectError 代码 expired页:1 个人按 GitHub 键取消,或 cancel(),拒绝方式 declined两者 存储什么。 任何提供者 device: { code, token } 端点工作 同样的方式.

在电脑上循环

import { connectLoopback } from '@byokit/connect/node';
import type { Keystore } from '@byokit/secrets';

declare const store: Keystore;
declare const yourApp: { openExternal(url: string): Promise<void> };

const attempt = await connectLoopback('notion', {
  store, person: 'Umer',
  open: url => yourApp.openExternal(url),
});
await attempt.done;
const connection = attempt.connection;
// Or attempt.cancel() to close the listener and reject done.

听者只绑住 127.0.0.1,有一个OS指定端口, 并关闭成功, 取消、 失败或超时 。 主机打开浏览器;工具包从不运行CLI. 使用 connect() 与 redirectUri 用于网络/PWA或本地验证会话.

完整的 MCP 客户端

import { connect, CallToolResultSchema } from '@byokit/connect';
import type { Keystore } from '@byokit/secrets';

declare const store: Keystore;

const notion = connect('notion', {
  store, person: 'Umer', redirectUri: 'https://your-app.example/connect/callback',
});
// Sign in once, then reconstruct this handle across app restarts.
const mcp = await notion.mcp({
  clientInfo: { name: 'your-app', version: '1' },
  clientOptions: { capabilities: {} },
  configure: client => { /* register SDK request/notification handlers here */ },
});
try {
  const page = await mcp.listTools(); // Follow nextCursor when present.
  const result = await mcp.callTool({ name: page.tools[0].name, arguments: {} }, CallToolResultSchema);
  // result preserves text, images, structuredContent, isError and other MCP data.
  const resources = await mcp.listResources();
  const prompts = await mcp.listPrompts();
} finally {
  await mcp.close();
}

mcp() 返回官方 SDK Client被困在1.31.0号 它输入的工具, 资源、提示、标记、取消、采样/删除处理器, 通知,通用计划验证 request() 和运输谈判中止 可用。 软件包再出口 Client 和 SDK 的协议类型/计划 通过。 流式HTTP支持JSON和SSE响应和会话头. 每个请求都获得该人的当前符号,范围被限制在被连接的资源上. 401会触发一次刷新/重试;拒绝重定向. 先关闭客户端 disconnect() 释放出他们的溪流。 任意无认证的 MCP 服务器和 遗留的 HTTP + SSE 传输在此签名包初始范围之外.

列出要连接的应用程序

import { catalog, connect, knownApps, mcpDirectory } from '@byokit/connect';
import type { Keystore } from '@byokit/secrets';

declare const store: Keystore;
const apps = await catalog([knownApps, mcpDirectory('https://directory.your-app.example/v0/servers?version=latest')]);
const app = apps[0]; // { id, name, icon?, auth, ...the Provider connect() takes }
const connection = connect(app, { store, person: 'Umer', redirectUri: 'https://your-app.example/connect/callback' });
const flow = await connection.signIn(); // Or connectLoopback(app, ...); deviceSignIn(app, ...) when app.auth is 'device'.

catalog(sources) 按此顺序列出主机所选择来源的应用程序; a id两次列出它的第一个条目。 没有列出,也没有读到 默认。 每个上市的应用程序都是 Provider,所以它通过同样的 connect(), (中文(简体) ), connectLoopback() 财务报告和审定财务报表 deviceSignIn() 如上,在同项下 键盘记录为该id的预设. auth 说如何: oauth 需要应用程序 登记 client, (中文(简体) ), discovery 在应用程序的 MCP 服务器上找到签名 登记自己提供, device 显示输入的代码. icon 是一个 HTTPS 来自列表的图像地址; 使其成为不可信内容 .

  • knownApps 列出工具包的预设providers)并读出无.
  • mcpDirectory(url, { fetch?, timeoutMs? }) 读取远程 MCP 目录 mCP 登记册中的答复 GET /v0/servers 形状,后面 metadata.nextCursor (最多100页),仅在上市时使用. 它保持服务器 有可流的HTTP遥控器,没有地址变量或所需的信头; 本地软件包,遗留的SSE远程和密钥头服务器被忽略. URL 网络 必须是 HTTPS( 或回转); 对于 MCP 登记册添加 version=latest。 。 。 .
  • 任何对象 list(): Promise<CatalogApp[]> 是一个源, 如主机 拥有其服务器后方的管理连接器目录 .

disconnect() 返回时 { revokedAtApp: true } 当应用程序接受撤销,否则 { revokedAtApp: false, reason: 'failed' | 'unsupported' }。当授权元数据发布 RFC 7009 撤销端点时,它会在删除本地记录之前发送刷新符和访问符。 一个失败的请求从不会阻止本地删除 .

当 MCP 请求返回 403 WWW-Authenticate: Bearer error="insufficient_scope"它拒绝 ConnectError 代码 insufficient_scope 财务报告和审定财务报表 requiredScopes 当服务器提供范围提示时。 开始 connection.stepUp(error.requiredScopes ?? ['scope']);返回的登录请求增加范围,所节省的赠款一直可用到 finish() 存储升级的赠款.

以另一个形状拒绝失败或回答的目录 ConnectError 代码 catalog 联合国 status),是无法接触的 network;整个 catalog() 打电话拒绝, 所以列出一个来源 单独保存其余. 主机为它命名的目录提供担保: 签入一个列出的应用程序谈话 到列出名称的服务器.

读取和搜索 Gmail

import { connect, MailReader } from '@byokit/connect';
import type { Keystore } from '@byokit/secrets';
declare const store: Keystore;
const gmail = connect('gmail', { store, person: 'Umer', redirectUri: 'https://your-app.example/connect/callback' });
const mail = new MailReader(gmail, { maxBodyChars: 20_000 });
const page = await mail.search('invoice'); // Gmail syntax; follow page.nextPageToken.
const message = await mail.get(page.messages[0].id); // Envelope plus bounded body.

search编号 :list 返回一页信封; get 添加已解码的正文, 切到 maxBodyChars (单位:千美元)body.truncated 说吧 401次重复,然后读作 签出; 费率限制携带 until 从 Retry-After。 。 。 .

发送Gmail, 每封信一次批准

import { connect, MailSender, type OutgoingMail } from '@byokit/connect';
import type { Keystore } from '@byokit/secrets';
declare const store: Keystore;
declare function askPerson(mail: OutgoingMail): Promise<boolean>; // The host's own confirm step.
const gmail = connect('gmail', { store, person: 'Umer', redirectUri: 'https://your-app.example/connect/callback',
  scopes: ['https://www.googleapis.com/auth/gmail.send'] });
const sender = new MailSender(gmail, mail => askPerson(mail));
const sent = await sender.send({ to: '[email protected]', subject: 'Invoice paid', body: 'Thanks, Umer' });

发送需要 gmail.send 范围,请求通过 scopes (无赠款的赠款) 无法登录 scope) (中文(简体) ). 每个 send 要求批准一次 与被冻结 信件将编码; 只 true 发送,和任何其他,包括一发, 实值 MailError 代码 denied 在任何代号或提供商呼叫之前 每条一条 调用:不进行分批、排队、重试或背景发送。 网络故障离开 结果未知, 请在请求再次发送前先检查 Sent 。 简单文字正文 只显示赤裸的地址: 没有 cc/bcc, 显示名称、 HTML, 附件, 答复 a 线程或标签.

所有者入境的历史和出口

import { MailHistory, type Connection } from '@byokit/connect';
declare const gmail: Connection; // Signed in for Umer.
const history = new MailHistory(gmail, { owner: 'Umer' });
const rows = await history.messages({ principal: 'Umer', query: 'invoice' });
const csv = await history.export({ principal: 'Umer', query: 'invoice', format: 'csv' }); // Or 'json'.

主机绑定 owner 一次;每次呼叫名称 principal 还有别的 被拒绝(HistoryError 代码 denied在任何提供者获取之前。 检索 页面通过 search编号 :list 最多 maxMessages (默认100起,最多500起). 导出只写信封——消息机构从不被导出. 供应商 失败者留着 MailError 代码, status 财务报告和审定财务报表 until 下级 HistoryError。 。 。 .

刷新、出错和存储

重新刷新值在过期后一分钟内或401后进行。 没错 单飞相通柄共享相同的键盘对象/人/接. 旋转的刷新令牌被坚持;省略刷新令牌的回复保留 前一个。 短暂的失败保留了登录。 只有明确 invalid_grant 将取去. 网络后仍可使用未过期的令牌 失败; 过期的符号永远不会返回 。 没有 expires_in 保留 无效直至被拒绝,然后尽可能刷新。 不需要背景计时器 .

ConnectError.code 是一个打入的应用程序诊断和 message 是一个简单的句子. OAuth 错误显示可选键 cause 与 error 财务报告和审定财务报表 error_description,根据提供/归还的证书和URL进行消毒. 信息仍然是一句平话。 将提供者描述视为不信任 文本;它们是对宿主的诊断,而不是即时放弃UI. 无出错或 标记被登录。 MCP结果/错误是私人应用内容,应当 将相应对待. fetch, (中文(简体) ), now,请求和流出时间可以注射.

按键依赖提供共享类型Script合同;没有后端 运行时导入。 传出任何 @byokit/secrets 后端( 或一个) 执行它的主机适配器 get编号 :set编号 :delete (合同)。 包里写着一个 JSON秘密,包括赠款、刷新信使、范围、发行人/端点和 按固定散列时间计算 名称。 使用耐用设备 存储; 不将此记录发送到共享服务器。 见 警卫 用于货币和回调边界.

密封桌面令牌存储

在节点或Electron的主要过程中,在通过前将主机的耐用商店包好 它连接。 此适配器只写已认证的密码文本, 包括之后 刷新;店名被捆绑在被封装的有效载荷内.

import { connect } from '@byokit/connect';
import { osKeyringSeal, type Keystore } from '@byokit/secrets/node';

// Your app's durable, per-person store; it receives ciphertext only.
declare const ciphertextStore: Keystore;
const seal = osKeyringSeal({ service: 'crewhouse-connect-Umer', dualWrap: true });
const store: Keystore = {
  async get(name) {
    const value = await ciphertextStore.get(name);
    if (value === null) return null;
    const record = JSON.parse(seal.decryptString(Buffer.from(value, 'base64')));
    if (record.name !== name || typeof record.secret !== 'string') throw new Error('Stored sign-in could not be opened.');
    return record.secret;
  },
  async set(name, secret) {
    const bytes = seal.encryptString(JSON.stringify({ name, secret }));
    await ciphertextStore.set(name, Buffer.from(bytes).toString('base64'));
  },
  delete: name => ciphertextStore.delete(name),
};
const notion = connect('notion', {
  store, person: 'Umer', redirectUri: 'https://your-app.example/connect/callback',
});

每人保留一个适配器/存储实例和应用程序,如果 多个进程共享存储. 双层包装许可证只通过所有者读取 当密钥环被锁定时, 主机密钥; 将密钥与密码文本备份分开 . 奥米 dualWrap 通过 fallback: false 当需要可用的OS密钥环时. 见 保密指南 页:1 平台行为、密钥保护和旋转。 签名并正常刷新通过 连接控件; 永远不要将其返回的访问符分开.

船员领养

替换 OAuth、 令牌文件和 RemoteMcp 页:1 src/connections.ts 与 每个成员/应用程序一个处理器,列出来自 catalog([knownApps]) (编) mcpDirectory(url) 或主机自己的来源列出更多). 通过会员的密钥和会员ID,房子谷歌 客户端来自 googleClientFile 以及机组人员的回电地址 保留 流控在主机的回调路由表中直到完成/取消. 乘务员保留了自己的连接屏幕,Google设置了指导和工具门. 对于远程应用程序,呼叫 mcp() 和使用情况 listTools编号 :callTool * 取得全面成果; 用于 Gmail 用户 MailReader编号 :MailSender 下面; 用于日历 token() 直到其输入的工具包 坐在这个连接上。 任何原始的OAuth,刷新或MCP运输都需要留在消费者体内.

核查

npm run build
npm run check
sh scripts/test.sh 'packages/connect/test/*.test.ts'

packages/connect/test/journey-connect.test.ts 驱动已建软件包的方式 a 主机app does - connect编号 :signIn编号 :deviceSignIn编号 :token编号 :mcp, (中文(简体) ), catalog 超过已知的应用程序和a 循环回放 MCP 目录( 一个上市的应用连接端到端), 循环回放听器, 家 谷歌客户端, MailReader编号 :MailSender 财务报告和审定财务报表 MailHistory假的供应商和一个真正的 只能回回调 。 包括PKCE/状态和精确召回装订,每人 隔离、更新种族和取消、发现/DCR/资源约束、丰富的MCP JSON/SSE 响应,批准/拒绝发送,所有者覆盖的历史和浏览器 捆绑. 不使用真账或出网通话. 现场直播 这些测试不要求供应商/设备的登录.

版本与发布记录

@byokit/connect 共发布 10 个版本,首次发布于 2026/10/01;过去 12 个月发布了 10 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.8.1latest2026/10/2514 天前
0.8.02026/10/1921 天前
0.7.02026/10/1821 天前
0.6.02026/10/1822 天前
0.5.12026/10/1822 天前
0.5.02026/10/1722 天前

关于 @byokit/connect 的常见问题

@byokit/connect 是什么?

TypeScript套件让人们通过他们已经支付的人工智能计划,在网络,电话和桌面上登录到你的应用程序.

如何安装 @byokit/connect?

在项目目录运行 npm install @byokit/connect,或使用 pnpm add / yarn add / bun add。

@byokit/connect 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@byokit/connect 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@byokit/connect 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@byokit/connect 可以商用吗?

@byokit/connect 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@byokit/connect 的下载量有多少?

根据 npm 官方下载统计,@byokit/connect 在 2026/10/09 – 2026/11/07 这 30 天内被下载 2,067 次,日均约 69 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@byokit/connect 还在维护吗?

最新版本 0.8.1 发布于 2026/10/25(14 天前);至今共发布 10 个版本,其中过去 12 个月发布了 10 个;首次发布于 2026/10/01。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。