@arbidocs/sdk

中文文档
0.5.132发布于 2026/11/06MITTypeScriptESM + CJS近 30 天下载 6万

Shared operations layer for ARBI — auth, config, SSE, WebSocket, and API operations

原始使用文档
文档目录24 节
  1. Quickstart
  2. Add a chat widget
  3. Lifecycle
  4. Operations
  5. Streaming AI queries
  6. Existing callback integrations
  7. Which workspace a turn runs in
  8. Which workspace other calls act in
  9. Session recovery
  10. Security
  11. React
  12. Requirements
  13. Automations
  14. Releases
  15. Errors and streaming outcomes
  16. Composable response handles
  17. Node example and package check
  18. Configuring HTTP transport
  19. Validated structured responses
  20. Familiar Responses operations
  21. Compose an existing configuration
  22. Choose a public layer
  23. Check setup
  24. Human review

@arbidocs/sdk

TypeScript SDK for the ARBI platform. Handles authentication, workspace encryption, and streaming AI queries.

Start below. The complete developer quickstart and compatibility table also ship in the npm package at node_modules/@arbidocs/sdk/docs/; no repository access is required.

Quickstart

npm install @arbidocs/sdk
import { Arbi } from '@arbidocs/sdk'

const arbi = new Arbi({ url: 'https://your-arbi-deployment.example' })
await arbi.login(email, password)
await arbi.selectWorkspace(workspaceId) // an explicit choice
const response = await arbi.responses.create({ input: 'Say hello in one sentence.' })
console.log(response.output_text)

Browser-only code imports the same API from @arbidocs/sdk/browser. For a rendered chat, use the basic React example or the website iframe. Node.js needs no IndexedDB polyfill. Keys stay in memory for this SDK instance unless you supply an explicit persistence adapter:

import { Arbi } from '@arbidocs/sdk'

Add a chat widget

The installed SDK includes a standalone React starter (in releases containing this guide):

cp -R node_modules/@arbidocs/sdk/examples/react-chat ./my-arbi-chat
cd my-arbi-chat
mv gitignore .gitignore
npm install
cp .env.example .env
# Set the public VITE_ARBI_URL, then:
npm run dev

Sign in inside the widget and explicitly choose a workspace. To deploy, run npm run build and serve dist/ as a static site. Never put credentials in VITE_ variables. The deployment must allow this app's origin for API calls. The app uses @arbidocs/blocks/embed, with matching package versions and stylesheet setup already supplied.

For a website without a React build pipeline, use the frontend deployment's hosted panel:

<iframe src="https://YOUR-ARBI-FRONTEND/embed/chat" title="ARBI chat"
  style="width:380px;height:640px;border:0" allow="clipboard-write"></iframe>

The panel owns sign-in and workspace choice. Your deployment must allow the host site to frame this route; the parent CSP must allow the frontend in frame-src. This is authenticated workspace chat. Embedded storage restrictions can require a separate sign-in.

Lifecycle

const arbi = new Arbi({ url: 'https://www.arbidocs.com' })

await arbi.login(email, password)            // or arbi.loginWithKey(email, keyBase64)
await arbi.selectWorkspace(workspaceId)
// ... use the SDK ...
await arbi.logout()
PropertyDescription
arbi.isLoggedInWhether the user is authenticated
arbi.hasWorkspaceWhether a workspace is selected
arbi.getDeploymentDomain()The domain the user's keys are derived for: the deploymentDomain option, else the hostname of url (e-signing re-derives keys with it)

Operations

NamespaceKey methods
arbi.workspaceslist(), create(), update(), delete(), listUsers(), addUsers(), removeUsers()
arbi.documentslist(), get(), uploadFile(), uploadUrl(), update(), delete(), download()
arbi.conversationslist(), getThreads(), updateTitle(), share(), delete()
arbi.responsescreate(), parse(), retrieve(), attach(), cancel() — start here for new integrations
arbi.assistantask(request, handlers), attachRun(responseId, handlers), interject(messageId, text), cancel(responseId), retrieve(query, docIds)
arbi.tagslist(), create(), update(), delete()
arbi.doctagsassign(), remove(), generate()
arbi.contactslist(), add(), remove()
arbi.healthcheck(), models(), mcpTools()

Streaming AI queries

const stream = await arbi.responses.create({ input: 'What does section 3 say?', stream: true })
for await (const event of stream) {
  if (event.type === 'response.output_text.delta') console.log(event.delta)
  if (event.type === 'response.failed') console.error(event.response.error)
}

Existing callback integrations

assistant.ask remains supported and uses /v1/responses. New integrations can start with responses.create above; keep the callback helper when your UI already uses it.

const result = await arbi.assistant.ask(
  {
    question: 'What does section 3 say?',
    docIds: [docId],
    previousResponseId: lastMessageId, // for multi-turn conversations
  },
  {
    onToken: (token) => { /* append to UI */ },
    onStreamStart: ({ assistant_message_ext_id }) => { /* save for follow-ups */ },
    onOutputItemDone: (event) => { /* an agent step settled */ },
    onError: (error) => { /* the server's report (string) or the connection (Error) */ },
    onComplete: () => { /* done */ },
  }
)

// result.text — full accumulated response
// result.assistantMessageExtId — use as previousResponseId for follow-ups

Which workspace a turn runs in

A turn runs in workspaceId (default: the current workspace), read when ask or startResponse is called and named on the request, so a workspace switch while it is sent cannot move it. A workspace other than the current one is opened for this session first (its key is deposited; the current workspace does not change). A follow-up runs in its thread's workspace: if the server refuses it with 409 workspace_mismatch, the turn is sent once more there, and onWorkspace(workspaceId) reports where it was accepted. A 409 workspace_key_required deposits the key again and resends once. When the workspace cannot be opened, nothing is sent and the call rejects with ArbiWorkspaceUnavailableError. workspaceConflictOf(error) reads either 409. assistant.submit and assistant.retrieve take workspaceId the same way.

Which workspace other calls act in

Facts (facts.create, createBatch, list, search), conversations (conversations.list, search, createWork, plan), assistant.listSkills, files.list and files.upload act in the current workspace, or in the workspaceId option they are given, which is opened for this session first without becoming current. Either way the request names the workspace (workspace_ext_id), so a switch while it is sent cannot move it. A note, a task or a conversation changed by id is changed in its own workspace, which the server derives from it. A refusal for the workspace (409 workspace_key_required, or workspace_mismatch for a sub-task whose parent is in another workspace) is an ArbiApiError with that code, saying nothing was saved.

Session recovery

Browsers persist the signing key encrypted in IndexedDB. Without IndexedDB, each SDK client keeps its own key in memory; it is not shared with other instances or saved to disk. Recover a session without a password:

await arbi.loginWithKey('[email protected]', signingKeyBase64)

The SDK also auto-recovers on 401 responses using the stored key.

Security

  • Zero-knowledge auth — passwords never leave the client
  • E2E workspace encryption — symmetric keys wrapped with your public key
  • Encrypted key storage — private keys in IndexedDB encrypted with non-extractable AES-GCM
  • Session cleanup — logout ends the live session; the stored identity supports offline unlock and default storage is cleared on logout-everywhere

React

For React apps, use @arbidocs/react instead — it wraps this SDK with hooks and a context provider. See the @arbidocs/react README.

Requirements

  • Browser: Any modern browser with Web Crypto API
  • Node.js: native fetch/Web Crypto runtime; Node 22+ is used by the executable example and package smoke check (no fake-indexeddb needed)
  • TypeScript: 5.0+ (optional)

Automations

The workflows namespace exposes create/get/list/update/delete/run and listWorkflowRuns. Triggers use schedules or notification types; every saved rule can also run immediately. A document action (annotate_documents or email_documents) returns an execution reference rather than a conversation. Its persisted history contains selected documents, run-label references, result metadata and failures; annotation answers remain document fields. Every execution has a WorkflowRuns record; chat actions also link to a conversation.

import { workflows } from '@arbidocs/sdk'
const run = await workflows.runWorkflow(arbi, 'wfl-example')
if (run.error) throw new Error(run.error)
if (run.execution_id) {
  const history = await workflows.listWorkflowRuns(arbi, 'wfl-example')
  console.log(history)
}

Document selectors can specify IDs, labels resolved at execution time, or latest documents since the previous successful run. Unattended document actions require an assistant with standing workspace access; creating a rule does not grant that access.

For latest-document digests, the first run covers the preceding 24 hours; later runs use the previous successful run cutoff. Failed delivery does not advance it. Emails contain document names and authenticated platform links, without attachments.

Releases

Published versions are listed on npm. Maintainers with repository access can also read the detailed GitHub release notes.

Errors and streaming outcomes

SDK HTTP failures retain their structured server body in ArbiApiError.apiError, with status, detail, and optional code, requestId, and responseId. AssistantTurnRefused remains an ArbiApiError when ask() rejects. Network failures use ArbiTransportError and retain the original cause; native AbortError objects propagate unchanged.

ask(), attachRun(), and streamSSE() retain their existing callbacks and result fields. Add onErrorDetails(error) to inspect typed errors alongside the legacy onError callback, and onOutcome(outcome) to observe the terminal result. SDK stream results also include outcome and errorDetails. The outcome preserves the existing assistant msg- identifier and raw terminal response payload. Its status is completed, failed, cancelled, incomplete, disconnected, or acknowledged. A control-only acknowledgement has no response identity. The legacy completed boolean still indicates receipt of response.completed; use outcome.status to distinguish the server's explicit terminal status.

A local abort or truncated connection reports disconnected, with reason aborted, connection_closed, or connection_error; it never proves that the server cancelled execution. Reader failures reject as well as notifying the outcome. Explicit terminal server events finish reading without waiting for the connection to close. The first terminal frame wins: later frames, including conflicting terminals or tokens in the same chunk, are ignored. Background response APIs continue to expose the original Responses envelope and its status and error fields.

Consumer callback exceptions propagate unchanged. They do not trigger a second typed error or outcome notification and are not classified as server failures or transport disconnections. onOutcome fires once when SDK consumption reaches an outcome; an earlier consumer exception interrupts consumption before that notification.

Composable response handles

assistant.startResponse(request, { signal }) uses the same request builder and workspace selection as ask. It returns either an observer for the existing msg-… response, or a control acknowledgement without inventing a message. Existing ask, callbacks, and attachRun remain supported.

const started = await arbi.assistant.startResponse({ question: 'Summarize this document', docIds })
if (started.kind === 'response') {
  const handle = started.handle
  const unsubscribe = handle.subscribe((snapshot) => render(snapshot.displayText))
  try {
    const outcome = await handle.outcome
    if (outcome.status === 'disconnected') {
      const stored = await arbi.assistant.getResponse(handle.id)
      // Inspect stored status; attachResponse(handle.id) again if still active.
    }
  } finally {
    unsubscribe()
    handle.detach()
  }
}

Use await handle.cancel() for an explicit authenticated server cancellation request. detach() and the optional AbortSignal only close this reader. A cancellation request does not settle the handle as cancelled: the terminal server event decides the outcome. Workspace and native-agent permissions continue to be enforced by the server.

attachResponse('msg-…') observes the existing watch stream, with its bounded replay retention; a 404 requires stored-response/history reconciliation. Handles do not retry or reconnect in the background, and an attachment's disconnected outcome does not mean server execution stopped.

Snapshots and their output items are immutable. Subscriptions immediately receive the current snapshot, including fast completion. Exceptions in a snapshot listener are rethrown in a microtask without stopping the reader or other listeners. Unknown server statuses and raw terminal results are preserved. displayText is the existing rendering projection, not a final-answer selector.

handle.events() provides one live raw iterator, beginning when called. It preserves unknown JSON events/fields and SSE IDs; reasoning frames retain their raw text. Malformed JSON and conflicting response IDs produce arbi.sdk.protocol_error diagnostics with the original frame. This is not retrospective replay or a durable resume cursor. Keep existing callbacks when every startup frame is needed. The iterator buffers at most 256 frames, covering existing tool and control fixtures; overflow rejects its reads with code RESPONSE_EVENT_OVERFLOW, while snapshot reduction continues. Return/break the iterator to release its buffer; a second iterator is rejected.

Node example and package check

Run examples/node-response.mjs with Node 22+ after installing @arbidocs/sdk (node node_modules/@arbidocs/sdk/examples/node-response.mjs). Set ARBI_URL, ARBI_EMAIL, ARBI_PASSWORD and ARBI_WORKSPACE_ID; ARBI_QUESTION is optional. It explicitly selects the current workspace, submits one Responses turn, distinguishes disconnect from completion and refetches an accepted response rather than resubmitting it. Ctrl-C detaches the reader; it does not claim to cancel background execution.

Default Node storage lasts only for that client instance. For persistence across process restarts, pass persistence: { getSession, saveSession, clearSession } to Arbi or createArbiClient. The existing SessionPersistence interface is retained; clearSession is optional for existing adapters and is invoked by logout-everywhere when provided. Protect keys in any custom persistent store. Normal logout retains the stored identity for the existing offline-unlock behavior; logout-everywhere clears the default memory adapter. Browser encrypted storage remains unchanged.

Repository maintainers can run node scripts/sdk-node-smoke.mjs after building the client and SDK. It packs both packages, installs their tarballs/runtime dependencies in a fresh temporary npm consumer, checks ESM/CommonJS/browser/testing imports and exercises key login, recovery and Responses over a local fake fetch. It requires the npm registry for dependencies, no deployment credentials, and no IndexedDB polyfill. It verifies package/runtime behavior, not backend access control or live deployment integration.

Configuring HTTP transport

React Query still manages React caches, mutations and refetching. The SDK transport underneath it can be configured once for typed requests, Responses streams and multipart API uploads:

const arbi = new Arbi({
  url: 'https://arbi.example.com',
  transport: {
    fetch: customFetch, // optional fetch-compatible adapter
    timeoutMs: 30_000, // optional; no deadline by default
    onResponse: ({ method, url, status, durationMs }) => {
      recordRequest({ method, url, status, durationMs })
    },
  },
})

For a host-owned session, configure transport on createArbiClient and pass that client to Arbi; its wrapper inherits the host transport and session gate. Configure it on the host, rather than supplying a different transport to the wrapper. Existing host client adapters without http retain the previous global-fetch fallback for raw SDK operations.

The timeout lasts until the adapter returns a Response: response headers for native fetch, or the buffered reply for the XMLHttpRequest upload-progress adapter. It does not cap a live stream's body. AbortSignal cancellation and sign-out still stop the body after headers. Metadata hooks receive method, sanitized URL (no query, fragment or credentials), status and elapsed time; no headers or bodies are passed. onError receives the original fetch failure. Hooks are opt-in and synchronous; a thrown hook exception rejects the request. No telemetry or logging is enabled by default.

Default browser uploads retain XMLHttpRequest byte progress. An injected fetch takes precedence over XHR and reports upload completion once rather than promising byte progress. The existing presigned storage PUT adapter, public booking helpers, media downloads and WebSockets are separate transports and are not changed by this API-transport option.

Connection failures are retried only for generated GET/HEAD requests, with the existing bounded backoff. Mutations and response creation are never retried after an ambiguous connection failure. Existing explicit authentication/workspace-state refusal recovery remains, through the same configured transport. This option adds no workspace selector, header, permission or switching.

Validated structured responses

const format = {
  type: 'json_schema' as const,
  name: 'invoice',
  strict: true,
  schema: {
    type: 'object',
    properties: { total: { type: 'number' } },
    required: ['total'],
    additionalProperties: false,
  },
}
const response = await arbi.responses.parse<{ total: number }>({
  input: 'Extract the total from: Invoice total 125.50',
  text: { format },
})
// response.output_parsed.total is validated; output, usage and metadata are retained.

The same text option is accepted by ask, startResponse and background submit. For streaming/background work, retain the format and validate a completed resource with await parseStructuredResponse(response, format). Live JSON fragments are provisional. The parser expects one final assistant output message; it does not join narrative and answer messages or treat metadata.content as a replacement for standard output items.

Invalid JSON, schema mismatch, refusal, incomplete/cancelled/nonterminal responses and invalid schemas have distinct error codes. ArbiStructuredOutputError.response preserves the original response; request/response IDs remain available. No type coercion, default insertion, Markdown repair or automatic resubmission is performed. The TypeScript generic describes your schema's shape; runtime validation comes from JSON Schema, not the generic parameter.

Schemas use draft 2020-12 and local references; format annotations are not asserted. Client validation loads Ajv on demand and uses runtime compilation, with logging disabled. A runtime policy that prohibits compilation produces STRUCTURED_OUTPUT_VALIDATOR_UNAVAILABLE before sending a request; raw server-validated Responses remain available through the existing APIs without this client parser.

Requires the backend structured-output capability. It validates the existing model/agent loop's final answer without changing workspace, identity or tool permissions. Native-agent and slash/delegation paths that cannot honor this contract reject it explicitly with STRUCTURED_OUTPUT_UNSUPPORTED; they never silently ignore it. Other request fields and old callback consumers keep their existing behavior.

Familiar Responses operations

const response = await arbi.responses.create({ input: 'Hello', model: 'cfg-my-config' })
console.log(response.output_text)
const stream = await arbi.responses.create({ input: 'Hello', stream: true })
for await (const event of stream) {
  if (event.type === 'response.output_text.delta') process.stdout.write(event.delta)
}
const queued = await arbi.responses.create({ input: 'Review this', background: true })
const current = await arbi.responses.retrieve(queued.id)

The current workspace supplies the ARBI workspace context. workspace_ext_id is a wire-level escape hatch subject to existing server checks; it does not switch the session or grant access. create and retrieve retain the envelope's output, metadata, usage and terminal state, and add an output_text convenience field. create also exposes _request_id when the server provides it. A failed JSON response remains a failed response; inspect status and error.

create({ stream: true }) returns an async iterable of events with a standard type discriminator. The existing message observer buffers events from the first frame and applies backpressure, so fast replies and slow consumers do not lose the beginning. Iteration throws on a disconnected reader; failed/incomplete terminal frames remain observable as events. Breaking iteration detaches the reader and leaves server execution running. Explicit cancellation uses responses.cancel(id). The optional stream.handle exposes ARBI snapshots, outcomes, detach and cancellation.

The existing responses.stream and assistant.startResponse methods still return ARBI handles (or slash-command acknowledgements). Use those helpers for control commands. Streaming background creation is currently unsupported and rejected before HTTP; create with background: true, then use responses.attach(id) for existing replay/live events. One con- contains many msg- responses.

For structured results, responses.parse<T>({ input, text: { format } }) returns output_parsed alongside output_text and the original output fields. It validates the JSON Schema before sending one synchronous request; failures/refusals/incomplete results throw the existing structured error. The schema is plain JSON Schema, not a Zod-specific helper. assistant.parseResponse and the standalone parseStructuredResponse remain supported for existing consumers. These SDK patterns follow the official Responses streaming guide and structured-output guide.

Compatibility means the documented /v1/responses subset, not drop-in support for every OpenAI, Anthropic or Vercel feature. Input is currently a string; tool context uses ARBI's documented tool map. Authentication, cfg selection, agt identity, workspace grants and deferred execution remain ARBI contracts. Native local-function tools and arbitrary provider options are not implemented. See the backend's docs/responses-api.md for the exact supported fields.

Compose an existing configuration

Start from the configuration fetched by agentConfig.get(configId) so omitted settings keep their current values. No helper creates an identity, grants permissions or contacts MCP servers.

import { composeConfiguration, instructions, capabilities, mcpTools,
  documentTools, composeTools } from '@arbidocs/sdk/browser'

const existingConfiguration = { ...await arbi.agentConfig.get(configId), title: 'Evidence review' }
const updated = composeConfiguration(existingConfiguration,
  instructions('Answer with evidence.'),
  capabilities({ webSearch: true, codeExecution: false }),
  mcpTools(existingConfiguration, ['approved_search'], 'add'))
await arbi.agentConfig.save(updated)
const tools = composeTools(existingTools, documentTools({ search: [documentId] }), 'add')
await arbi.responses.create({ input: 'Summarise the evidence', tools })

Configuration sections merge one level; arrays replace; explicit null clears. MCP and response-tool helpers require an explicit add or replace choice. Adding a tool replaces the same name while preserving other names. Instructions apply to both QueryLLM and the built-in agent persona. Ordinary cfg- configurations do not require agt- identities. Pinning a configuration to an existing agent uses the existing agent_ext_id; authorizing its task remains a separate action.

Choose a public layer

NeedPackage / entry
Responses and domain operations, Node@arbidocs/sdk
Same operations, browser-safe imports@arbidocs/sdk/browser
Typed HTTP and advanced crypto/session access@arbidocs/client
Headless React state and React Query hooks@arbidocs/react
Standalone chat widget@arbidocs/blocks/embed
Rendered composable views@arbidocs/blocks and capability subpaths
Connected rendered views@arbidocs/blocks/connect
Fake fetch, SSE frames, replay scenarios@arbidocs/sdk/testing (tests only)

Existing exports remain available. Import domain helpers through the documented package entries; never import src/ or generated dist/ internals. A React Query hook uses the same session and request builder as the SDK; applications do not need another chat engine.

The published examples/ directory includes node-response.mjs, stream-response.mjs, background-response.mjs and structured-extraction.mjs. response-handle.mjs shows the optional ARBI lifecycle controls. Install the package, set the environment variables documented in examples/session.mjs, and run with Node 22+. Background inspection accepts an existing response ID and never resubmits automatically. Tests can import frame and createSseFake from /testing to exercise streams without a deployment (see the exported helper signatures).

Check setup

Run await arbi.diagnose() or arbi doctor --json to check deployment, session and current-workspace setup without logging in, switching workspaces or granting access. See the packaged diagnostics guide.

Human review

A runnable example ships at node_modules/@arbidocs/sdk/examples/human-review. Copy it to a local folder, rename gitignore to .gitignore, install dependencies, configure .env, then run npm start -- start. The example prints the existing conversation ID and commands to inspect, send back, and explicitly approve its draft. It resumes the same workflow conversation across processes using existing step APIs. See its README.

版本与发布记录

@arbidocs/sdk 共发布 487 个版本,首次发布于 2026/02/10;过去 12 个月发布了 487 个版本。

版本发布日期距今
0.5.132latest2026/11/061 天前
0.5.1312026/11/061 天前
0.5.1302026/11/052 天前
0.5.1292026/11/052 天前
0.5.1282026/11/052 天前
0.5.1272026/11/052 天前

关于 @arbidocs/sdk 的常见问题

@arbidocs/sdk 是什么?

Shared operations layer for ARBI — auth, config, SSE, WebSocket, and API operations

如何安装 @arbidocs/sdk?

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

@arbidocs/sdk 支持 TypeScript 吗?

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

@arbidocs/sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@arbidocs/sdk 可以商用吗?

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

@arbidocs/sdk 的下载量有多少?

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

@arbidocs/sdk 还在维护吗?

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