Skip to content

TypeScript SDK

TypeScript SDK 安装、认证、操作调用、错误和流式事件的公开入口。

Updated View as Markdown

标识

@appaloft/sdk 是面向自动化和集成的操作客户端——它调用 Appaloft 的 HTTP/oRPC API,不嵌入应用运行时,也不暴露内部实现细节。SDK 方法直接对应 OpenAPI 契约中的业务操作;不存在单独添加的、脱离业务操作目录的 SDK 专属方法。

安装与配置

import { createAppaloftClient } from "@appaloft/sdk";

const appaloft = createAppaloftClient({
  baseUrl: "https://appaloft.example/api",
});

baseUrl 应指向同一个 Appaloft 实例的 /api 根路径。自托管环境应优先使用安装脚本打印的控制台/API 地址。

认证

场景凭据类型
交互式产品操作产品会话 Cookie
机器自动化(CI、脚本)Deploy Token(Bearer)
const productClient = createAppaloftClient({
  baseUrl: "https://appaloft.example/api",
  auth: { kind: "product-session", cookie: "better-auth.session_token=..." },
});

const actionClient = createAppaloftClient({
  baseUrl: "https://appaloft.example/api",
  auth: { kind: "deploy-token", token: process.env.APPALOFT_TOKEN ?? "" },
});

不要把 Deploy Token 写入仓库配置文件;在 CI 中应通过受信任的密钥管理或环境变量注入。组织范围通过具体操作的 path/query/body 字段传递(例如 organizationId),切换当前组织应调用公开的组织切换操作,而不是在 SDK 内维护隐藏状态。

操作示例

每个 SDK 调用对应一个操作 key,输入字段来自同一套 Command/Query Schema:

const created = await appaloft.projects.create({ name: "Demo" });
const listed = await appaloft.projects.list({ limit: 20 });
const shown = await appaloft.projects.show({ projectId: "prj_123" });

if (!created.ok) {
  // created.error 是结构化 Appaloft 错误
  throw new Error(created.error.code);
}

Facade 方法名从操作 key 生成:kebab-case 转为 camelCase,点号转为嵌套分组。例如 dependency-resources.provisioning.plan 会生成 dependencyResources.provisioning.plan

Path 参数可以作为顶层字段传入;剩余字段在 GETDELETE 和流式操作中默认进入 query,在其他操作中默认进入 JSON body。需要精确控制拆分时,可以显式传入 pathParamsquerybody

Sandbox 资源句柄

Sandbox 所有权链使用资源句柄,调用方不需要重复传递父级 id:

const sandbox = await appaloft.sandboxes.create(sandboxInput);

try {
  const agent = await sandbox.agents.create({ harness: "pi" });
  const run = await agent.stream({ prompt: "Analyze and update the workspace" });

  for await (const envelope of run.fullStream) {
    if (envelope.kind === "event") console.log(envelope.eventType, envelope.data);
    if (envelope.kind === "error") throw new Error(envelope.code);
  }
} finally {
  await sandbox.terminate();
}

Agent 是 Sandbox Agent Runtime 的 SDK 别名,agent.stream({ task }) 会创建一个 Run 并把持久化事件作为 fullStream 返回;prompt 是方便从 AI SDK 迁移的 task 别名。Appaloft 不接管聊天会话——调用方仍负责保存消息并决定何时使用全新上下文或 parentRunId 续接。

需要一次创建 Sandbox 和 Runtime 时,可以使用公共 Workspace 入口:

const workspace = await appaloft.workspaces.create({ sandbox: sandboxInput, harness: "opencode" });

workspaceId 等于 sandboxId;如果 Runtime 创建失败,AppaloftWorkspaceCreateError 仍会携带已创建的 id,便于重试或清理。详见 Sandbox 模型

资源方法直接返回 descriptor,失败时抛出 AppaloftSdkRequestError;需要完整且不抛异常的 { ok, status, data/error } facade 时使用 appaloft.operations,例如 appaloft.operations.sandboxes.create(input)

结构化错误

生成的操作返回稳定的结构化错误字段:codecategorymessageretryable 和可选 details;资源句柄会把相同的安全字段暴露在 AppaloftSdkRequestError 上。自动化应该判断 codecategoryretryable,不要解析人类可读的 message

常见认证错误:

Code含义
product_auth_missing / product_auth_invalid产品会话缺失、过期或不可验证
product_auth_forbidden当前用户不属于目标组织,或角色不足
action_auth_missing / action_auth_invalidDeploy Token 凭据缺失或无效
action_auth_forbiddenDeploy Token 有效,但作用域不覆盖当前请求

完整错误模型见错误码与状态

流式事件

只有 OpenAPI 元数据标记为可流式的操作才能使用 SDK 的流式 Helper。调用方应该传入 AbortSignal 来取消长连接,并按结构化 envelope 处理心跳、事件、缺口(gap)、关闭和错误:

const controller = new AbortController();

for await (const envelope of appaloft.deployments.streamEvents({
  deploymentId: "dep_123",
  signal: controller.signal,
})) {
  if (envelope && typeof envelope === "object" && "kind" in envelope) {
    // 处理 event、heartbeat、gap、closed 或 error envelope
  }
}

当流返回 closed 或调用方取消 AbortSignal 后,自动化应该停止读取并按需重新打开流。流式 Facade 方法返回 AsyncIterable,不会把整个 SDK 改成 throw-only 模式——普通请求 Facade 仍返回 { ok, status, data }{ ok, status, error }

相关任务

Navigation

Type to search…

↑↓ navigate↵ selectEsc close