Zum Hauptinhalt springen

API-Referenz

Vollständige Referenz für @telepat/otto-sdk Version 0.1.x.

OttoClient

Der Haupteinstiegspunkt für alle SDK-Operationen.

Konstruktor

new OttoClient(options: {
relayUrl: string;
clientId: string;
clientSecret: string;
})
OptionTypBeschreibung
relayUrlstringRelay-WebSocket-URL. Akzeptiert wss://- oder ws://-Schema.
clientIdstringController-Client-ID, erhalten von der Relay-Registrierung.
clientSecretstringController-Client-Secret, erhalten von der Relay-Registrierung.
const client = new OttoClient({
relayUrl: 'wss://relay.example.com',
clientId: 'clt_abc123',
clientSecret: 'cs_xxxxxxxxxxxx',
});

connect(): Promise<void>

Tauscht Anmeldeinformationen gegen ein JWT-Access-Token ein und öffnet dann einen authentifizierten WebSocket zum Relay.

  • Idempotent — sicher bei Mehrfachaufruf. No-Op, wenn bereits verbunden.
  • Wird automatisch beim ersten Zugriff auf client.nodes, client.commands oder client.listeners aufgerufen.
await client.connect();

Wirft: OttoAuthError, wenn die Anmeldeinformationen ungültig sind.

disconnect(): Promise<void>

Schließt die WebSocket-Verbindung ordnungsgemäß. Löscht das gespeicherte Access-Token.

await client.disconnect();

isConnected(): boolean

Gibt true zurück, wenn der WebSocket geöffnet und authentifiziert ist.

if (!client.isConnected()) {
await client.connect();
}

client.nodes

list(): Promise<Node[]>

Gibt alle Nodes zurück, die mit dem Relay verbunden sind und einen aktiven ACL-Grant für diesen Controller haben.

const nodes = await client.nodes.list();
// [{ nodeId: 'node_local_1' }, ...]

Rückgabetyp:

interface Node {
nodeId: string;
}

Wirft: OttoError bei Relay- oder Netzwerkfehler.


client.commands

list(options): Promise<CommandDescriptor[]>

Listet alle verfügbaren Befehle auf einem Node auf.

const commands = await client.commands.list({ nodeId: 'node_local_1' });

Optionen:

FeldTypBeschreibung
nodeIdstringZiel-Node-ID.

Rückgabetyp:

interface CommandDescriptor {
site: string; // Domain, auf die der Befehl abzielt (z. B. 'reddit.com')
id: string; // Eindeutiger Befehlsidentifikator
displayName: string; // Menschenlesbarer Name
description: string; // Beschreibung der Funktion des Befehls
tags: string[]; // Durchsuchbare Labels
requiresAuth: boolean; // Ob der Benutzer auf der Site angemeldet sein muss
inputFields: CommandInputFieldDescriptor[];
}

interface CommandInputFieldDescriptor {
name: string;
type: string; // 'string' | 'number' | 'boolean' | 'object'
required: boolean;
description: string;
defaultValue?: unknown;
}

Wirft: OttoCommandError, wenn der Node die Anfrage ablehnt.

run(options): Promise<CommandResult>

Führt einen Befehl auf einem Node aus und wartet auf das Ergebnis.

const result = await client.commands.run({
nodeId: 'node_local_1',
site: 'reddit.com',
command: 'getPosts',
input: { subreddit: 'typescript', limit: 10 },
timeoutMs: 30000,
});

Optionen:

FeldTypErforderlichBeschreibung
nodeIdstringZiel-Node-ID.
sitestringSite-Domain (z. B. 'reddit.com', 'linkedin.com').
commandstringBefehlsidentifikator (z. B. 'getPosts', 'getChatMessages').
inputRecord<string, unknown>Eingabe-Payload für den Befehl.
timeoutMsnumberMaximale Wartezeit in Millisekunden. Standard: 30000.

Rückgabetyp:

interface CommandResult {
ok: boolean;
data?: unknown; // Befehlsausgabe
commandOutcome: 'completed' | 'failed' | 'timed_out' | 'cancelled';
durationMs: number; // Ausführungszeit in ms
error?: string; // Fehlermeldung, wenn nicht ok
}

Wirft:

  • OttoCommandError — Befehl fehlgeschlagen, Timeout oder abgebrochen. Enthält die Eigenschaft commandOutcome.
  • OttoTimeoutError — SDK-Level-Timeout (keine Antwort innerhalb von timeoutMs + 5s erhalten).

client.listeners

subscribe(options): StreamSession

Abonniert einen Listener-Stream auf einem Node. Gibt sofort eine StreamSession zurück; das Abonnement beginnt, wenn Sie mit dem Konsumieren von Ereignissen beginnen (über for await oder .on()).

const stream = client.listeners.subscribe({
nodeId: 'node_local_1',
listener: 'network.http_intercept',
options: { site: 'reddit.com', pattern: 'https://reddit.com/api/*' },
});

Optionen:

FeldTypErforderlichBeschreibung
nodeIdstringZiel-Node-ID.
listenerstringListener-Identifikator (z. B. 'network.http_intercept').
optionsRecord<string, unknown>Listener-spezifische Konfiguration.

Gibt zurück: StreamSession


StreamSession

Wird von client.listeners.subscribe() zurückgegeben. Implementiert sowohl AsyncIterable<ListenerUpdateEvent> als auch EventEmitter.

Async-Iteration

for await (const event of stream) {
console.log(event.type); // 'listener_update'
console.log(event.data); // Ereignis-Payload
}

Die Schleife endet, wenn Sie break aufrufen, stream.unsubscribe() aufrufen oder der Stream endet.

EventEmitter-API

stream.on('data', (event: ListenerUpdateEvent) => {
console.log(event.data);
});

stream.on('error', (error: Error) => {
console.error('Stream-Fehler:', error.message);
});

stream.on('end', () => {
console.log('Stream beendet');
});

start(): Promise<void>

Startet das Abonnement explizit. Wird automatisch aufgerufen, wenn Sie mit der Iteration beginnen oder einen Event-Listener hinzufügen.

await stream.start();

unsubscribe(): Promise<void>

Sendet eine Deabonnierungs-Nachricht an den Node, emittiert 'end' und beendet jede aktive for await-Schleife.

await stream.unsubscribe();

Ereignistyp:

interface ListenerUpdateEvent {
type: 'listener_update';
data: unknown; // Listener-spezifischer Payload
updateType?: string; // Optionaler Untertyp
emittedAt?: string; // ISO-Zeitstempel
}

client.pairing

listPending(): Promise<PairingChallenge[]>

Gibt Kopplungsanfragen zurück, die auf Controller-Genehmigung warten.

const pending = await client.pairing.listPending();
for (const challenge of pending) {
console.log(challenge.code, challenge.nodeId, challenge.status);
}

Rückgabetyp:

interface PairingChallenge {
challengeId: string;
code: string; // 6-stelliger Genehmigungscode
nodeId: string;
status: 'pending' | 'approved' | 'expired';
expiresAt: string; // ISO-Zeitstempel
}

approve(options): Promise<void>

Genehmigt eine ausstehende Kopplungsanfrage.

await client.pairing.approve({ code: '123456' });

Optionen:

FeldTypBeschreibung
codestring6-stelliger Kopplungscode von listPending() oder dem Erweiterungs-Popup.

Wirft: OttoError, wenn der Code nicht genau 6 Ziffern hat oder die Anfrage nicht gefunden wird.


Fehlertypen

Alle Fehlertypen erweitern OttoError, das Error erweitert. Importieren Sie sie für typisierte catch-Blöcke.

import {
OttoError,
OttoAuthError,
OttoTimeoutError,
OttoCommandError,
} from '@telepat/otto-sdk';

OttoError

Basisklasse für alle SDK-Fehler.

class OttoError extends Error {
name: 'OttoError';
}

OttoAuthError

Wird geworfen, wenn der Anmeldeinformationsaustausch fehlschlägt (falsche clientId oder clientSecret, Token widerrufen usw.).

class OttoAuthError extends OttoError {
name: 'OttoAuthError';
}

OttoTimeoutError

Wird geworfen, wenn das SDK keine Antwort innerhalb des konfigurierten Timeouts erhält.

class OttoTimeoutError extends OttoError {
name: 'OttoTimeoutError';
}

OttoCommandError

Wird geworfen, wenn ein Befehl mit einem nicht-completed-Ergebnis abschließt.

class OttoCommandError extends OttoError {
name: 'OttoCommandError';
commandOutcome: string; // 'failed' | 'timed_out' | 'cancelled'
}

Fehlerbehandlungsmuster

import { OttoError, OttoAuthError, OttoTimeoutError, OttoCommandError } from '@telepat/otto-sdk';

try {
await client.commands.run({ nodeId, site: 'reddit.com', command: 'getPosts' });
} catch (err) {
if (err instanceof OttoAuthError) {
// Anmeldeinformationen sind falsch oder Token wurde widerrufen
} else if (err instanceof OttoTimeoutError) {
// Keine Antwort vom Node innerhalb des Timeout-Fensters
} else if (err instanceof OttoCommandError) {
console.error('Ergebnis:', err.commandOutcome); // 'failed' | 'timed_out' | 'cancelled'
} else if (err instanceof OttoError) {
// Anderer Relay-/Protokollfehler
} else {
throw err; // Unerwartete Fehler erneut werfen
}
}

Typ-Exporte

Alle öffentlichen Typen werden vom Paket-Root exportiert:

import type {
Node,
CommandDescriptor,
CommandInputFieldDescriptor,
CommandResult,
PairingChallenge,
ListenerUpdateEvent,
} from '@telepat/otto-sdk';