Skip to content

Antara Muka Utama

Halaman ini mendokumentasikan antara muka TypeScript yang mentakrifkan titik sambungan Triggerfish. Jika anda membina penyesuai saluran tersuai, pembekal LLM, backend storan, atau integrasi dasar, inilah kontrak yang mesti dipenuhi oleh kod anda.

Result<T, E>

Triggerfish menggunakan jenis hasil kesatuan yang didiskriminasi sebagai ganti pengecualian yang dilemparkan untuk semua kegagalan yang dijangka.

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

Penggunaan:

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

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

Jangan pernah melempar pengecualian untuk kegagalan yang dijangka. Gunakan Result<T, E> sepanjang masa. Pengecualian yang dilemparkan dikhaskan untuk ralat yang benar-benar tidak dijangka dan tidak dapat dipulihkan (pepijat). :::

ClassificationLevel

Sistem pengkelasan empat peringkat yang digunakan untuk semua keputusan aliran data.

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

Tertib dari tertinggi ke terendah: RESTRICTED > CONFIDENTIAL > INTERNAL > PUBLIC. Data hanya boleh mengalir ke peringkat yang sama atau lebih tinggi (tiada tulis-bawah).

StorageProvider

Abstraksi kegigihan bersatu. Semua data berkeadaan dalam Triggerfish mengalir melalui antara muka ini.

typescript
interface StorageProvider {
  /** Simpan nilai di bawah kunci yang diberikan. Menimpa mana-mana nilai sedia ada. */
  set(key: string, value: string): Promise<void>;

  /** Ambil nilai mengikut kunci. Mengembalikan null apabila kunci tidak wujud. */
  get(key: string): Promise<string | null>;

  /** Padam kunci. Tiada operasi apabila kunci tidak wujud. */
  delete(key: string): Promise<void>;

  /** Senaraikan semua kunci yang sepadan dengan awalan pilihan. Mengembalikan semua kunci apabila tiada awalan diberikan. */
  list(prefix?: string): Promise<string[]>;

  /** Lepaskan sumber yang dipegang oleh pembekal ini (contoh, tutup pemegang pangkalan data). */
  close(): Promise<void>;
}

Pelaksanaan:

BackendKes Penggunaan
MemoryStorageProviderPengujian, sesi sementara
SqliteStorageProviderLalai untuk peringkat peribadi (SQLite WAL di ~/.triggerfish/data/triggerfish.db)
Backend perusahaanDiurus oleh pelanggan (Postgres, S3, dsb.)

Ruang nama kunci: sessions:, taint:, lineage:, audit:, cron:, notifications:, exec:, skills:, config:

ChannelAdapter

Antara muka umum untuk semua penyesuai saluran pemesejan (CLI, Telegram, Slack, Discord, WhatsApp, WebChat, E-mel).

typescript
interface ChannelAdapter {
  /** Tahap pengkelasan yang diberikan kepada saluran ini. */
  readonly classification: ClassificationLevel;

  /** Sama ada pengguna semasa adalah pemilik. */
  readonly isOwner: boolean;

  /** Sambungkan ke saluran. */
  connect(): Promise<void>;

  /** Putuskan sambungan dari saluran. */
  disconnect(): Promise<void>;

  /** Hantar mesej ke saluran. */
  send(message: ChannelMessage): Promise<void>;

  /** Daftarkan pengendali untuk mesej masuk. */
  onMessage(handler: MessageHandler): void;

  /** Dapatkan status saluran semasa. */
  status(): ChannelStatus;
}

Jenis sokongan:

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

Antara muka untuk penyelesaian LLM. Setiap pembekal (Anthropic, OpenAI, Google, Tempatan, OpenRouter) melaksanakan antara muka ini.

typescript
interface LlmProvider {
  /** Pengecam nama pembekal. */
  readonly name: string;

  /** Sama ada pembekal ini menyokong respons penstriman. */
  readonly supportsStreaming: boolean;

  /** Hantar mesej ke LLM dan terima respons penyelesaian. */
  complete(
    messages: readonly LlmMessage[],
    tools: readonly unknown[],
    options: Record<string, unknown>,
  ): Promise<LlmCompletionResult>;
}

Daftar pembekal:

typescript
interface LlmProviderRegistry {
  /** Daftarkan pembekal. Menggantikan mana-mana pembekal sedia ada dengan nama yang sama. */
  register(provider: LlmProvider): void;

  /** Dapatkan pembekal mengikut nama, atau undefined jika tidak didaftarkan. */
  get(name: string): LlmProvider | undefined;

  /** Tetapkan pembekal lalai mengikut nama. Mesti sudah didaftarkan. */
  setDefault(name: string): void;

  /** Dapatkan pembekal lalai, atau undefined jika tiada yang ditetapkan. */
  getDefault(): LlmProvider | undefined;
}

NotificationService

Abstraksi penghantaran pemberitahuan. Lihat Pemberitahuan untuk perincian penggunaan.

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 {
  /** Hantar atau beraturkan pemberitahuan untuk pengguna. */
  deliver(options: DeliverOptions): Promise<void>;

  /** Dapatkan pemberitahuan yang belum dihantar untuk pengguna. */
  getPending(userId: UserId): Promise<Notification[]>;

  /** Akui pemberitahuan sebagai telah dihantar. */
  acknowledge(notificationId: string): Promise<void>;
}

Jenis Hook

Hook penguatkuasaan dasar memintas tindakan pada titik kritikal dalam aliran data. Semua hook adalah deterministik, sinkronus, dilog, dan tidak boleh dipalsukan.

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 dan 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

Unit asas keadaan perbualan dengan penjejakan taint bebas.

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

Jenis ID berjenama:

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

Jenis berjenama mencegah salah guna ID secara tidak sengaja -- anda tidak boleh menghantar UserId di mana SessionId dijangkakan.

Semua operasi sesi adalah tidak boleh diubah. Fungsi mengembalikan objek SessionState baru dan bukannya mengubah yang sedia ada. Ini memastikan ketelusan rujukan dan memudahkan pengujian. :::