Skip to content

关键接口

本页记录定义 Triggerfish 扩展点的 TypeScript 接口。如果你正在构建自定义渠道适配器、LLM 提供商、存储后端或策略集成,这些是你的代码必须满足的契约。

Result<T, E>

Triggerfish 使用可辨识联合结果类型而非抛出异常来处理所有预期失败。

typescript
type Result<T, E> =
  | { readonly ok: true; readonly value: T }
  | { readonly ok: false; readonly error: E };

用法:

typescript
function parseConfig(raw: string): Result<Config, string> {
  try {
    const config = JSON.parse(raw);
    return { ok: true, value: config };
  } catch {
    return { ok: false, error: "Invalid JSON" };
  }
}

const result = parseConfig(input);
if (result.ok) {
  // result.value 是 Config
} else {
  // result.error 是 string
}

永远不要为预期失败抛出异常。全程使用 Result<T, E>。抛出异常仅保留给真正意外的、不可恢复的错误(bug)。 :::

ClassificationLevel

用于所有数据流决策的四级分类系统。

typescript
type ClassificationLevel =
  | "RESTRICTED"
  | "CONFIDENTIAL"
  | "INTERNAL"
  | "PUBLIC";

从最高到最低排序:RESTRICTED > CONFIDENTIAL > INTERNAL > PUBLIC。数据只能流向相同或更高级别(禁止降级写入)。

StorageProvider

统一的持久化抽象。Triggerfish 中所有有状态数据都通过此接口流转。

typescript
interface StorageProvider {
  /** 在给定键下存储值。覆盖任何现有值。 */
  set(key: string, value: string): Promise<void>;

  /** 按键检索值。键不存在时返回 null。 */
  get(key: string): Promise<string | null>;

  /** 删除键。键不存在时无操作。 */
  delete(key: string): Promise<void>;

  /** 列出匹配可选前缀的所有键。无前缀时返回所有键。 */
  list(prefix?: string): Promise<string[]>;

  /** 释放此提供商持有的资源(例如关闭数据库句柄)。 */
  close(): Promise<void>;
}

实现:

后端使用场景
MemoryStorageProvider测试、临时会话
SqliteStorageProvider个人版默认(SQLite WAL 模式,位于 ~/.triggerfish/data/triggerfish.db
企业后端客户管理(Postgres、S3 等)

键命名空间: sessions:taint:lineage:audit:cron:notifications:exec:skills:config:

ChannelAdapter

所有消息渠道适配器(CLI、Telegram、Slack、Discord、WhatsApp、WebChat、Email)的通用接口。

typescript
interface ChannelAdapter {
  /** 分配给此渠道的分类级别。 */
  readonly classification: ClassificationLevel;

  /** 当前用户是否为所有者。 */
  readonly isOwner: boolean;

  /** 连接到渠道。 */
  connect(): Promise<void>;

  /** 断开渠道连接。 */
  disconnect(): Promise<void>;

  /** 向渠道发送消息。 */
  send(message: ChannelMessage): Promise<void>;

  /** 注册入站消息处理器。 */
  onMessage(handler: MessageHandler): void;

  /** 获取当前渠道状态。 */
  status(): ChannelStatus;
}

支持类型:

typescript
interface ChannelMessage {
  readonly content: string;
  readonly sessionId?: string;
  readonly sessionTaint?: ClassificationLevel;
}

interface ChannelStatus {
  readonly connected: boolean;
  readonly channelType: string;
}

type MessageHandler = (message: ChannelMessage) => void;

LlmProvider

LLM 补全的接口。每个提供商(Anthropic、OpenAI、Google、Local、OpenRouter)实现此接口。

typescript
interface LlmProvider {
  /** 提供商名称标识符。 */
  readonly name: string;

  /** 此提供商是否支持流式响应。 */
  readonly supportsStreaming: boolean;

  /** 向 LLM 发送消息并接收补全响应。 */
  complete(
    messages: readonly LlmMessage[],
    tools: readonly unknown[],
    options: Record<string, unknown>,
  ): Promise<LlmCompletionResult>;
}

提供商注册表:

typescript
interface LlmProviderRegistry {
  /** 注册提供商。替换同名的任何现有提供商。 */
  register(provider: LlmProvider): void;

  /** 按名称获取提供商,未注册则返回 undefined。 */
  get(name: string): LlmProvider | undefined;

  /** 按名称设置默认提供商。必须已注册。 */
  setDefault(name: string): void;

  /** 获取默认提供商,未设置则返回 undefined。 */
  getDefault(): LlmProvider | undefined;
}

NotificationService

通知投递抽象。使用详情参见通知

typescript
type NotificationPriority = "critical" | "normal" | "low";

interface Notification {
  readonly id: string;
  readonly userId: UserId;
  readonly message: string;
  readonly priority: NotificationPriority;
  readonly createdAt: Date;
}

interface DeliverOptions {
  readonly userId: UserId;
  readonly message: string;
  readonly priority: NotificationPriority;
}

interface NotificationService {
  /** 为用户投递或排队通知。 */
  deliver(options: DeliverOptions): Promise<void>;

  /** 获取用户的待投递(未投递)通知。 */
  getPending(userId: UserId): Promise<Notification[]>;

  /** 确认通知已投递。 */
  acknowledge(notificationId: string): Promise<void>;
}

Hook 类型

策略执行 hook 在数据流的关键点拦截操作。所有 hook 都是确定性的、同步的、有日志记录的和不可伪造的。

HookType

typescript
type HookType =
  | "PRE_CONTEXT_INJECTION"
  | "PRE_TOOL_CALL"
  | "POST_TOOL_RESPONSE"
  | "PRE_OUTPUT"
  | "SECRET_ACCESS";

PolicyAction

typescript
type PolicyAction = "ALLOW" | "BLOCK" | "REDACT" | "REQUIRE_APPROVAL";

HookContext 和 HookResult

typescript
interface HookContext {
  readonly session: SessionState;
  readonly input: Record<string, unknown>;
}

interface HookResult {
  readonly allowed: boolean;
  readonly action: PolicyAction;
  readonly ruleId: string | null;
  readonly message?: string;
  readonly duration: number;
}

SessionState

具有独立 taint 跟踪的对话状态基本单元。

typescript
interface SessionState {
  readonly id: SessionId;
  readonly userId: UserId;
  readonly channelId: ChannelId;
  readonly taint: ClassificationLevel;
  readonly createdAt: Date;
  readonly history: readonly TaintEvent[];
}

品牌 ID 类型:

typescript
type SessionId = string & { readonly __brand: "SessionId" };
type UserId = string & { readonly __brand: "UserId" };
type ChannelId = string & { readonly __brand: "ChannelId" };

品牌类型防止 ID 的意外误用——你不能在期望 SessionId 的地方传入 UserId

所有会话操作都是不可变的。函数返回新的 SessionState 对象而非改变现有对象。这确保引用透明性并简化测试。 :::