@rine-network/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,40 @@
1
+ /**
2
+ * AbortSignal helpers for composable cancellation.
3
+ *
4
+ * Provides:
5
+ * - `timeoutSignal(ms)` — `{ signal, clear }` pair that aborts after ms ms
6
+ * with an `RineTimeoutError` reason. Callers MUST call `clear()` in a
7
+ * `finally` block so the timer is cancelled on early completion
8
+ * (audit MINOR-4, SPEC_v2 §14.3).
9
+ * - `anySignal(...signals)` — signal that aborts when ANY of the inputs abort
10
+ */
11
+ /**
12
+ * Create a signal that fires after `ms` milliseconds.
13
+ *
14
+ * Returns a `{ signal, clear }` pair. Callers MUST invoke `clear()` in a
15
+ * `finally` block (or equivalent) to cancel the timer on early completion —
16
+ * otherwise the timer will still fire, aborting an already-settled signal
17
+ * and leaking a timer handle per call. `clear()` is idempotent.
18
+ *
19
+ * When the timer fires, the signal is aborted with an `RineTimeoutError`
20
+ * reason so `catch` sites can distinguish an SDK timeout from a user-cancel
21
+ * via `err instanceof RineTimeoutError` (SPEC_v2 §14.4).
22
+ */
23
+ export declare function timeoutSignal(ms: number): {
24
+ signal: AbortSignal;
25
+ clear: () => void;
26
+ };
27
+ /**
28
+ * Combine multiple signals into one that aborts when ANY input aborts.
29
+ *
30
+ * The composed signal's `reason` is the reason from whichever input fired
31
+ * first — this preserves the `RineTimeoutError` reason attached by
32
+ * `timeoutSignal()` (and matching per-op timers in resources), so downstream
33
+ * `signal.reason instanceof RineTimeoutError` checks classify timeouts
34
+ * correctly instead of seeing a generic `AbortError` (SPEC_v2 §14.4).
35
+ *
36
+ * Listeners are detached from the remaining inputs as soon as the combined
37
+ * signal fires — this prevents retaining long-lived source signals (e.g. a
38
+ * global client signal) through short-lived request signals.
39
+ */
40
+ export declare function anySignal(...signals: AbortSignal[]): AbortSignal;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * CursorPage<T> — async iterable + hasNext/hasPrev.
3
+ *
4
+ * Mirrors the Python SDK's CursorPage[T] pattern. The caller-passing
5
+ * `autoPaginate(fetchPage)` method was deleted per SPEC §13.3 — use the
6
+ * dedicated `client.inboxAll()` / `client.discoverAll()` / `client.discoverGroupsAll()`
7
+ * async generators instead, which own their fetch loop.
8
+ */
9
+ /**
10
+ * Cursor-paginated response.
11
+ *
12
+ * @typeParam T - Item type (DecryptedMessage, AgentSummary, etc.)
13
+ */
14
+ export declare class CursorPage<T> implements AsyncIterable<T> {
15
+ readonly items: T[];
16
+ readonly total: number;
17
+ readonly nextCursor: string | null;
18
+ readonly prevCursor: string | null;
19
+ constructor(items: T[], total: number, nextCursor: string | null, prevCursor: string | null);
20
+ get hasNext(): boolean;
21
+ get hasPrev(): boolean;
22
+ [Symbol.asyncIterator](): AsyncGenerator<T>;
23
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Standard Schema v1 integration helpers — SPEC §7.4 / §11.4.
3
+ *
4
+ * The SDK accepts user-supplied schemas on `send<T>`, `read<T>`, `reply<T>`,
5
+ * `messages<T>`, `sendAndWait<Req, Rep>`, `conversation(id).{send,reply,messages,history}<T>`,
6
+ * and `defineAgent<T>`. `@standard-schema/spec` is a type-only package — no
7
+ * validator runtime ships with the SDK (D3). Users bring Zod, Valibot, ArkType,
8
+ * Effect Schema, or any other compliant library and pass a schema object via
9
+ * the `schema` option slot.
10
+ *
11
+ * Two exported helpers:
12
+ *
13
+ * - `parsePlaintext<T>(value, schema)` — validates an arbitrary plaintext
14
+ * value against a Standard Schema v1 and returns the typed output. Throws
15
+ * `ValidationError` on the first issue reported by the schema.
16
+ *
17
+ * - `parseMessagePlaintext<T>(msg, schema)` — wraps `parsePlaintext` with
18
+ * the JSON-parse step specific to `DecryptedMessage.plaintext` (which is
19
+ * a string coming out of rine-core's `decryptMessage` / `decryptGroupMessage`
20
+ * helpers) and returns a `DecryptedMessage<T>` with the typed plaintext
21
+ * folded back in. If `msg.plaintext` is `null` (decrypt failed upstream)
22
+ * the message is returned untouched — the schema is not applied to a
23
+ * `decrypt_error` envelope.
24
+ */
25
+ import type { StandardSchemaV1 } from "@standard-schema/spec";
26
+ import type { DecryptedMessage } from "../types.js";
27
+ export type { StandardSchemaV1 };
28
+ /**
29
+ * Validate an arbitrary value against a Standard Schema v1 and return the
30
+ * typed output. The validator may return a synchronous result or a promise,
31
+ * so this helper always awaits. On failure, the first issue's message is
32
+ * used as the `ValidationError` detail — detail enough to point at the
33
+ * field without dumping the full issue list into the error message.
34
+ */
35
+ export declare function parsePlaintext<T>(value: unknown, schema: StandardSchemaV1<unknown, T>): Promise<T>;
36
+ /**
37
+ * JSON-parse a `DecryptedMessage.plaintext` string and validate it via a
38
+ * Standard Schema v1, returning a typed `DecryptedMessage<T>`. Leaves
39
+ * messages with `plaintext == null` untouched (decrypt-failed envelopes
40
+ * still surface to the caller so they can branch on `decrypt_error`).
41
+ *
42
+ * The JSON-parse step is mandatory: Standard Schemas like Zod's `z.object`
43
+ * validate structured input, not raw strings. If a caller's payload is
44
+ * already a plain string, they can use `z.string()` as the schema and the
45
+ * JSON-parse round-trip is still well-defined (`JSON.parse('"hi"') === "hi"`).
46
+ */
47
+ export declare function parseMessagePlaintext<T>(msg: DecryptedMessage, schema: StandardSchemaV1<unknown, T>): Promise<DecryptedMessage<T>>;
48
+ /**
49
+ * Validate an outbound payload against a Standard Schema v1 before it is
50
+ * handed to the encryption layer. SPEC §11.4: outbound schemas run *before*
51
+ * encrypt so a shape failure rejects without sending any ciphertext.
52
+ *
53
+ * This helper returns the validated (possibly transformed — schemas may
54
+ * parse / coerce) value so the caller can encrypt the narrowed form rather
55
+ * than the raw input. For schemas that are pure type guards (no transforms)
56
+ * the returned value is reference-equal to the input.
57
+ */
58
+ export declare function validateOutbound<T>(payload: T, schema: StandardSchemaV1<unknown, T>): Promise<T>;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Bounded FIFO seen-ID set.
3
+ *
4
+ * Used by both the SSE stream layer (reconnect replay dedup per SPEC_v2 §12.3.3)
5
+ * and the poll-based `watch()` path (see `client.ts`). On reconnect with
6
+ * `Last-Event-ID`, the server's catch-up phase can race with the NOTIFY
7
+ * delivery and re-emit events already seen; this class is the guard against
8
+ * dispatching them twice.
9
+ *
10
+ * Capacity defaults to 500 (SPEC §12.3.3 N — ~18 KB of RAM, ~10 minutes of
11
+ * traffic at 1 msg/s — comfortably larger than any plausible reconnect
12
+ * replay window, small enough to stay negligible).
13
+ */
14
+ export declare class SeenIds {
15
+ private readonly capacity;
16
+ private readonly set;
17
+ private readonly queue;
18
+ constructor(capacity?: number);
19
+ /** Returns true if the id is new (caller should dispatch), false if duplicate. */
20
+ record(id: string): boolean;
21
+ has(id: string): boolean;
22
+ get size(): number;
23
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Shared sleep utility — avoids triplication across client.ts, polling.ts, streams.ts.
3
+ */
4
+ export declare function sleep(ms: number): Promise<void>;
5
+ /**
6
+ * Like `sleep()` but aborts early when the given signal fires. Used in
7
+ * polling/streaming loops so cancellation during backoff doesn't wait
8
+ * the full interval.
9
+ */
10
+ export declare function sleepWithSignal(ms: number, signal?: AbortSignal): Promise<void>;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * SSE → AsyncIterable adapter.
3
+ *
4
+ * Converts an SSE (Server-Sent Events) stream into a native TypeScript
5
+ * AsyncIterable, so it composes with `for-await-of`, TransformStream, etc.
6
+ *
7
+ * The adapter:
8
+ * - Handles SSE line parsing (event:, data:, id:, :)
9
+ * - Dispatches accumulated events on blank lines (the SSE delimiter)
10
+ * - Yields structured `{ type, data, id }` objects
11
+ * - Couples with AbortSignal for cancellation
12
+ */
13
+ import type { RineEvent } from "../types.js";
14
+ /**
15
+ * Convert a fetch Response with an SSE body into an AsyncIterable of RineEvent.
16
+ *
17
+ * @param response - A fetch Response whose body is an SSE stream.
18
+ * @param signal - AbortSignal for cancellation.
19
+ *
20
+ * Usage:
21
+ * ```ts
22
+ * const resp = await fetch(url, { headers: { Accept: 'text/event-stream' } });
23
+ * for await (const event of toAsyncIter(resp, signal)) {
24
+ * console.log(event.type, event.data);
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function toAsyncIter(response: Response, signal: AbortSignal): AsyncGenerator<RineEvent>;
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@rine-network/sdk",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript SDK for Rine \u2014 E2E-encrypted messaging for AI agents",
5
+ "author": "Rine Network",
6
+ "license": "EUPL-1.2",
7
+ "type": "module",
8
+ "engines": {
9
+ "node": ">=22"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "default": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist/",
20
+ "CHANGELOG.md",
21
+ "LICENSE"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsdown src/index.ts --format esm --outDir dist --clean && tsc -p tsconfig.build.json",
25
+ "prepublishOnly": "npm run build",
26
+ "typecheck": "tsc --noEmit && tsc --noEmit -p examples/tsconfig.json",
27
+ "typecheck:examples": "tsc --noEmit -p examples/tsconfig.json",
28
+ "lint": "biome check .",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest",
31
+ "test:coverage": "vitest --coverage",
32
+ "dev": "tsx src/index.ts",
33
+ "docs": "typedoc"
34
+ },
35
+ "dependencies": {
36
+ "@rine-network/core": "^0.4.0",
37
+ "zod": "^3.24.0"
38
+ },
39
+ "devDependencies": {
40
+ "@biomejs/biome": "^1.9.0",
41
+ "@standard-schema/spec": "^1.1.0",
42
+ "@types/node": "^22.0.0",
43
+ "@vitest/coverage-v8": "^3.2.4",
44
+ "tsdown": "^0.12.0",
45
+ "tsx": "^4.19.0",
46
+ "typedoc": "^0.28.19",
47
+ "typedoc-plugin-markdown": "^4.11.0",
48
+ "typescript": "^5.7.0",
49
+ "vitest": "^3.0.0"
50
+ },
51
+ "homepage": "https://rine.network",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://codeberg.org/rine/rine-ts-sdk"
55
+ },
56
+ "bugs": {
57
+ "url": "https://codeberg.org/rine/rine-ts-sdk/issues"
58
+ },
59
+ "publishConfig": {
60
+ "access": "public"
61
+ },
62
+ "keywords": [
63
+ "messaging",
64
+ "ai-agents",
65
+ "sdk",
66
+ "a2a",
67
+ "e2ee",
68
+ "rine"
69
+ ]
70
+ }