@joai/sdk

中文文档
14.0.2发布于 2026/11/01MITTypeScriptES Module

JoAi公共API SDK -构建与您的AI代理

中文使用文档
文档目录3 节
  1. 托管内容编辑器
  2. 会话存储
  3. 编辑行为

@joai / sdk

React入口点包含可重用的构建块,用于在客户端网站上编辑内容。组件保持域中立:站点提供标识符、复制、样式挂钩和呈现字段;SDK拥有会话切换和编辑生命周期。

托管内容编辑器

import { ManagedContentEditor } from '@joai/react'

<ManagedContentEditor
  config={{
    contentId: 'content-id',
    publicSlug: 'website-content',
    sessionStorageKey: 'website-content-session',
    team: 'team-slug',
  }}
  initialContent={content}
  title="Inhalte bearbeiten"
  labels={{
    edit: 'Bearbeiten',
    save: 'Entwurf speichern',
    saving: 'Wird gespeichert …',
    publish: 'Veröffentlichen',
    publishing: 'Wird veröffentlicht …',
    cancel: 'Abbrechen',
    toolbar: 'Inhaltseditor',
    unsaved: 'Nicht gespeicherte Änderungen',
  }}
  messages={{
    conflict: 'Der Inhalt wurde zwischenzeitlich geändert. Deine Eingaben bleiben erhalten. Bitte prüfe sie und versuche es erneut.',
    loadError: 'Der Inhalt konnte nicht geladen werden.',
    publishError: 'Die Änderungen konnten nicht veröffentlicht werden.',
    published: 'Die Änderungen wurden veröffentlicht.',
    saveError: 'Der Entwurf konnte nicht gespeichert werden.',
    saved: 'Der Entwurf wurde gespeichert.',
    sessionExpired: 'Deine Sitzung ist abgelaufen.',
    unsavedNavigation: 'Du hast nicht gespeicherte Änderungen. Seite wirklich verlassen?',
  }}
  imagePickerLabels={{
    applyCrop: 'Zuschnitt übernehmen',
    back: 'Zurück',
    choose: 'Bild auswählen',
    close: 'Schließen',
    cropDescription: 'Passe Bildausschnitt und Zoom vor dem Hochladen an.',
    cropTitle: 'Bild zuschneiden',
    dimensionsTooLarge: 'Die Bildabmessungen sind zu groß.',
    dimensionsTooSmall: 'Die Bildabmessungen sind zu klein.',
    drop: 'Bild hier ablegen',
    empty: 'Noch keine Bilder vorhanden.',
    field: 'Bearbeitbares Bild',
    invalidType: 'Bitte wähle eine Bilddatei.',
    libraryDescription: 'Wähle ein vorhandenes Bild oder lade ein neues hoch.',
    libraryTitle: 'Bildmediathek',
    loadError: 'Bilder konnten nicht geladen werden.',
    loading: 'Bilder werden geladen …',
    positionHorizontal: 'Horizontale Position',
    positionVertical: 'Vertikale Position',
    processing: 'Bild wird vorbereitet …',
    retry: 'Erneut versuchen',
    tooLarge: 'Das Bild ist zu groß.',
    upload: 'Bild hochladen',
    uploadError: 'Das Bild konnte nicht hochgeladen werden.',
    uploading: 'Wird hochgeladen …',
    zoom: 'Zoom',
  }}
  reauthenticateLabel="Anmeldung erneuern"
  sessionExpiredMessage="Deine Sitzung ist abgelaufen. Deine lokalen Änderungen bleiben erhalten."
  confirmCancel={() => window.confirm('Nicht gespeicherte Änderungen verwerfen?')}
  confirmLeave={() => window.confirm('Du hast nicht gespeicherte Änderungen. Seite wirklich verlassen?')}
  confirmPublish={() => window.confirm('Änderungen jetzt veröffentlichen?')}
>
  {children}
</ManagedContentEditor>

使用 EditableContent, EditableImage, useContentValue 从 @joai/react 编辑器内部。将服务器获取的公共内容传递为 initialContent 以避免访问者的客户端加载状态。

将每个图像字段配置为可重用的、与领域无关的构建块。默认情况下,图像被压缩为WebP,最高可达2560 × 2560像素,而动画GIF和SVG文件保留其原始格式。每个领域的种植是可选择的:

<EditableImage
  field="heroImage"
  label="Titelbild"
  maxSourceBytes={40 * 1024 * 1024}
  maxUploadBytes={5 * 1024 * 1024}
  processing={{
    crop: { aspectRatio: 16 / 9, outputWidth: 1920 },
    compression: { maxWidth: 1920, maxHeight: 1080, mimeType: 'image/webp', quality: 0.84 },
    dimensions: { minWidth: 1280, minHeight: 720, maxPixels: 50_000_000 },
  }}
/>

集 compression: false 或者 dimensions: false 仅禁用该阶段,或者 processing={false} 上传原始图像,无需客户端解码、验证、裁剪或压缩。

会话存储

useContentSession 和 createSessionTokenStore 为自定义shell导出。一个自定义 SessionTokenStore 可以在主机需要不同的持久性机制时注入。包含一次性移交令牌的URL片段在交换和持久化之前被删除。

托管编辑器会自动添加 platform=app 到它的重新身份验证返回URL,这样JoAi返回一个一次性的移交令牌。覆盖 reauthenticateUrl 只有当主机有专用的登录回调时。

createContentDraftStore 使用 sessionStorage 默认情况下。 ManagedContentEditor 自动连接,使未保存的值在刷新和过期会话重新身份验证中存活下来,而不会跨浏览器会话共享。

编辑行为

  • 取消将恢复当前加载的版本。
  • 当没有本地更改时,将禁用Save。
  • 脏发布使用一个请求保存和发布。
  • 网络故障使本地编辑可用于重试。
  • 未保存编辑时,刷新、关闭和链接/导航尝试会发出警告。
  • 可编辑的文本和图像字段在编辑模式下可见地标记。
  • 图像库支持加载、空、错误、字节/尺寸验证、裁剪、压缩、键盘、焦点和拖放状态。
  • 过期的授权提供登录操作,并在之后恢复本地持久编辑。
  • 版本冲突将加载最新版本,同时保留本地编辑。
  • 公共内容缓存项在经过身份验证的更改之后无效。

版本与发布记录

@joai/sdk 共发布 84 个版本,首次发布于 2026/03/26;过去 12 个月发布了 84 个版本。

版本发布日期距今
14.0.2latest2026/11/011 天前
14.0.12026/11/012 天前
14.0.02026/10/312 天前
13.1.32026/10/313 天前
13.1.22026/10/313 天前
13.1.12026/10/304 天前

关于 @joai/sdk 的常见问题

@joai/sdk 是什么?

JoAi公共API SDK -构建与您的AI代理

如何安装 @joai/sdk?

在项目目录运行 npm install @joai/sdk,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@joai/core(^5.4.7)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@joai/sdk 支持 TypeScript 吗?

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

@joai/sdk 支持 ESM 还是 CommonJS?

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

@joai/sdk 需要什么版本的 Node.js?

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

@joai/sdk 可以商用吗?

@joai/sdk 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@joai/sdk 还在维护吗?

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