Lingara 开发者文档
本页译自英文。如两者有出入,以英文页面为准。 阅读英文页面
连接由步骤组成,任何步骤都可以带有脚本。步骤的脚本是一个函数的函数体。它接收两个值:lingara,即本页介绍的 API;以及 input,即该步骤自己的字段,连同它的客户端和在它之前连接的步骤。input 的类型取决于步骤的种类,因此 Webhook 步骤的脚本读取的是 Webhook 步骤的字段。脚本恰好返回一个对象,由下面的某个辅助函数构建。
脚本永远看不到密钥。当步骤需要它的客户端时,它会得到一个句柄,例如 input.client,辅助函数会记录这个句柄。你应用连接时,Lingara 会填入真实的值。
脚本不得做什么
脚本在你自己的浏览器中运行,位于一个没有网络、没有存储的 worker 中。它受以下限制:
- 它在 1 秒内完成。
- 它返回的字符串最多 2048 个字符。
- 它返回的列表最多 64 项。
- 它的整个结果最多 16 KiB。
违反限制、抛出异常或返回的不是某个辅助函数结果的脚本,会使其步骤失败,“开始检查”会显示是哪个步骤以及原因。
版本承诺
本页的一切都属于 lingara.v1。在 v1 中,API 只会增长:可能出现新的辅助函数、新的可选选项或新的步骤种类,但你今天能用的任何东西都不会被移除、重命名或收窄。会破坏脚本的更改将作为与此并列的新版本出现,而 v1 保持不变。
声明
下面的每个声明都由脚本编辑器进行自动补全所依据的同一个文件生成。
NodeHandle
另一个步骤的 id,例如 "n1"。依赖步骤通过句柄指定它的客户端。
export type NodeHandle = string;
Scope
API 客户端可以持有的一项权限。由服务器判断你的账户可以使用哪些。
export type Scope = 'vocab:generate' | 'lesson_plans:read' | 'lesson_plans:write' | 'tutor:converse' | 'usage:read' | 'events:read' | 'events:write' | 'embed:mint' | 'embed:play';
AppSlot
Lingara 应用中可以显示应用卡片的位置。
export type AppSlot = 'plans.empty_detail' | 'home.side';
ContextSlice
应用可以请求接收的学习者上下文的一部分。
export type ContextSlice = 'languages' | 'plan_summary' | 'review_due' | 'tutor_topic';
ClientOptions
lingara.client 的选项。
export interface ClientOptions {
name: string;
scopes: readonly Scope[];
redirectUris?: readonly string[];
}
name(string) — 客户端的名称,与开发者工具中显示的一致。scopes(readonly Scope[]) — 客户端请求的权限。redirectUris?(readonly string[]) — 授权码流程可以把学习者送回的位置。服务器对服务器的客户端可省略。
WebhookOptions
lingara.webhook 的选项。
export interface WebhookOptions {
client: NodeHandle;
url: string;
events: readonly string[];
}
client(NodeHandle) — 此 Webhook 所属的客户端步骤:input.client。url(string) — Lingara 投递事件的 HTTPS 地址。events(readonly string[]) — 要投递的事件类型,例如"lesson_plan.ready"。
ManifestOptions
lingara.manifest 的选项,使用 camelCase;辅助函数会写出清单的传输格式。
export interface ManifestOptions {
name: string | Readonly<Record<string, string>>;
description: string | Readonly<Record<string, string>>;
renderUrl: string;
slots: readonly AppSlot[];
context?: readonly ContextSlice[];
scopes?: readonly Scope[];
tutorNote?: boolean;
defaultLocale?: string;
}
name(string | Readonly<Record<string, string>>) — 应用的名称:一个字符串,或每个语言代码一个字符串。description(string | Readonly<Record<string, string>>) — 关于应用的一句话:一个字符串,或每个语言代码一个字符串。renderUrl(string) — Lingara 请求应用卡片的 HTTPS 地址。slots(readonly AppSlot[]) — 应用卡片可以出现的位置。context?(readonly ContextSlice[]) — 应用接收的上下文切片。默认为无。scopes?(readonly Scope[]) — 应用向学习者请求的权限。默认为无。tutorNote?(boolean) — 应用是否可以给导师留下备注。默认为false。defaultLocale?(string) — 纯字符串名称或描述所存储的语言代码。默认为"en"。
AppOptions
lingara.app 的选项。
export interface AppOptions {
client: NodeHandle;
manifest: Manifest;
}
client(NodeHandle) — 此应用所属的客户端步骤:input.client。manifest(Manifest) — 应用的清单,用lingara.manifest构建。
ClientSpec
客户端步骤创建的内容:一个 API 客户端。
export interface ClientSpec {
readonly kind: 'client';
readonly name: string;
readonly scopes: readonly Scope[];
readonly redirectUris?: readonly string[];
}
kind('client') — 始终为"client"。name(string) — 客户端的名称。scopes(readonly Scope[]) — 客户端请求的权限。redirectUris?(readonly string[]) — 客户端的重定向 URI(如果有)。
SecretSpec
密钥步骤创建的内容:为其客户端生成的新密钥。
export interface SecretSpec {
readonly kind: 'secret';
readonly client: NodeHandle;
}
kind('secret') — 始终为"secret"。client(NodeHandle) — 密钥所属的客户端步骤。
WebhookSpec
Webhook 步骤创建的内容:一个 Webhook 端点。
export interface WebhookSpec {
readonly kind: 'webhook';
readonly client: NodeHandle;
readonly url: string;
readonly events: readonly string[];
}
kind('webhook') — 始终为"webhook"。client(NodeHandle) — Webhook 所属的客户端步骤。url(string) — 事件投递到的地址。events(readonly string[]) — 投递的事件类型。
AppSpec
应用步骤创建的内容:一个在 Lingara 中渲染卡片的应用。
export interface AppSpec {
readonly kind: 'app';
readonly client: NodeHandle;
readonly manifest: Manifest;
}
kind('app') — 始终为"app"。client(NodeHandle) — 应用所属的客户端步骤。manifest(Manifest) — 应用的清单。
Manifest
传输格式的应用清单,与服务器存储的形式一致。
export interface Manifest {
readonly manifest_version: 1;
readonly default_locale: string;
readonly name: Readonly<Record<string, string>>;
readonly description: Readonly<Record<string, string>>;
readonly render_url: string;
readonly slots: readonly AppSlot[];
readonly context: readonly ContextSlice[];
readonly scopes: readonly Scope[];
readonly tutor_note: boolean;
}
manifest_version(1) — 始终为1。default_locale(string) — 学习者自己的语言没有条目时显示的语言。name(Readonly<Record<string, string>>) — 应用的名称,按语言代码区分。description(Readonly<Record<string, string>>) — 关于应用的一句话,按语言代码区分。render_url(string) — Lingara 请求应用卡片的 HTTPS 地址。slots(readonly AppSlot[]) — 应用卡片可以出现的位置。context(readonly ContextSlice[]) — 应用接收的上下文切片。scopes(readonly Scope[]) — 应用向学习者请求的权限。tutor_note(boolean) — 应用是否可以给导师留下备注。
Spec
辅助函数返回的任意 spec。脚本恰好返回一个。
export type Spec = ClientSpec | SecretSpec | WebhookSpec | AppSpec;
Upstream
每个直接上游步骤的输出,按句柄索引。
export type Upstream = Readonly<Record<NodeHandle, Spec & {
readonly handle: NodeHandle;
}>>;
ClientInput
客户端步骤的输入:它的字段,也就是 lingara.client 的选项。
export interface ClientInput {
readonly name: string;
readonly scopes: readonly Scope[];
readonly redirectUris?: readonly string[];
readonly upstream: Upstream;
}
name(string) — 客户端的名称。scopes(readonly Scope[]) — 客户端请求的权限。redirectUris?(readonly string[]) — 客户端的重定向 URI(如果该步骤有)。upstream(Upstream) — 每个直接上游步骤的输出。
SecretInput
密钥步骤的输入。client 是与此步骤连接的那个客户端步骤。
export interface SecretInput {
readonly client: NodeHandle;
readonly upstream: Upstream;
}
client(NodeHandle) — 与此步骤连接的客户端步骤。upstream(Upstream) — 每个直接上游步骤的输出。
WebhookInput
Webhook 步骤的输入:它的字段,加上连接的客户端。
export interface WebhookInput {
readonly client: NodeHandle;
readonly url: string;
readonly events: readonly string[];
readonly upstream: Upstream;
}
client(NodeHandle) — 与此步骤连接的客户端步骤。url(string) — 该步骤字段中指定的地址。events(readonly string[]) — 该步骤字段中指定的事件类型。upstream(Upstream) — 每个直接上游步骤的输出。
AppInput
应用步骤的输入:它的清单字段,加上连接的客户端。
export interface AppInput {
readonly client: NodeHandle;
readonly manifest: ManifestOptions;
readonly upstream: Upstream;
}
client(NodeHandle) — 与此步骤连接的客户端步骤。manifest(ManifestOptions) — 该步骤字段所描述的清单。upstream(Upstream) — 每个直接上游步骤的输出。
InputFor
给定种类的步骤脚本接收的输入。
export type InputFor<K extends Spec['kind']> = K extends 'client' ? ClientInput : K extends 'secret' ? SecretInput : K extends 'webhook' ? WebhookInput : AppInput;
LingaraV1
脚本调用的辅助函数。每个都返回一个冻结的 spec,类型错误的选项会抛出一个指明该选项的 TypeError。
export interface LingaraV1 {
readonly version: 'v1';
client(options: ClientOptions): ClientSpec;
secret(client: NodeHandle): SecretSpec;
webhook(options: WebhookOptions): WebhookSpec;
app(options: AppOptions): AppSpec;
manifest(options: ManifestOptions): Manifest;
}
version('v1') — 始终为"v1"。client(options: ClientOptions): ClientSpec— 一个 API 客户端。secret(client: NodeHandle): SecretSpec— 为客户端步骤生成的新密钥。webhook(options: WebhookOptions): WebhookSpec— 客户端步骤上的 Webhook 端点。app(options: AppOptions): AppSpec— 客户端步骤上的应用。manifest(options: ManifestOptions): Manifest— 传输格式的清单,并填入 v1 留作可选的那些选项。
return lingara.client({ name: input.name, scopes: input.scopes })
return lingara.secret(input.client)
return lingara.webhook({ client: input.client, url: input.url, events: input.events })
return lingara.app({ client: input.client, manifest: lingara.manifest(input.manifest) })
NodeScript
步骤的脚本就是这个函数的函数体:return lingara.webhook({ client: input.client, url: input.url, events: input.events })。
export type NodeScript<K extends Spec['kind']> = (lingara: LingaraV1, input: InputFor<K>) => Spec;