@rheonic/sdk 0.1.0-beta.2 → 0.1.0-beta.4

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.
package/README.md CHANGED
@@ -1,150 +1,132 @@
1
1
  # Rheonic Node SDK
2
2
 
3
- The Rheonic Node SDK runs inside your app process, captures provider telemetry, and can request protect preflight decisions before provider calls.
3
+ Rheonic captures provider telemetry and applies protect preflight decisions before provider calls.
4
4
 
5
5
  ## Install
6
6
 
7
- Beta prerelease install:
8
-
9
7
  ```bash
10
8
  npm install @rheonic/sdk
11
9
  ```
12
10
 
13
- Compatibility:
14
- - Node.js 18+
15
- - One of the supported provider SDKs: `openai`, `@anthropic-ai/sdk`, or `@google/generative-ai`
16
-
17
- Beta note:
18
- - Public beta releases may add guardrail fields and provider wrappers before `1.0.0`.
19
-
20
- ## Configuration
21
-
22
- - Required: `ingestKey`
23
- - Optional for local development: `baseUrl` (defaults to `RHEONIC_BASE_URL`, else `http://localhost:8000`)
24
- - Optional: `environment` (default `dev`)
25
-
26
- For hosted beta, staging, or production deployments, set `RHEONIC_BASE_URL` or pass `baseUrl` explicitly. The localhost default is intended only for local development.
27
-
28
- Provider/model validation: SDK wrappers fail fast with `RHEONICValidationError` when provider is missing/unsupported or model is missing/empty. Supported providers are `openai`, `anthropic`, and `google`. Model naming is not pattern-validated so future vendor naming changes remain compatible.
29
-
30
- ## Integration Recommendation
11
+ ## Required environment variables
31
12
 
32
- Create one long-lived SDK client at app startup and reuse it for all provider calls. The SDK prewarms tokenizer state and the backend connection on client initialization, so reusing a single client avoids paying protect cold-start cost on every request.
13
+ ```bash
14
+ RHEONIC_INGEST_KEY=<your_project_ingest_key>
15
+ RHEONIC_BASE_URL=<value_shown_in_dashboard>
16
+ ```
33
17
 
34
- ## Logging
18
+ ## Instrument provider calls
35
19
 
36
- The SDK emits structured JSON logs to stdout. You do not need to configure file logging.
20
+ Wrap your provider SDK once.
37
21
 
38
- Example log:
22
+ Telemetry is captured automatically after each provider call.
39
23
 
40
- ```json
41
- {
42
- "timestamp": "2026-03-18T09:20:15.145102+00:00",
43
- "level": "info",
44
- "service": "sdk-node",
45
- "env": "staging",
46
- "trace_id": "f4ac8b6b-6f8d-4f4c-b54f-3c2c2f76a27b",
47
- "span_id": "9f12db3a1d204f8f",
48
- "event": "sdk_client_initialized",
49
- "message": "SDK client initialized",
50
- "metadata": {}
51
- }
52
- ```
24
+ Enforcement follows Project mode in the dashboard (`Observe` / `Protect`).
53
25
 
54
- Notes:
55
- - backend requests automatically include `X-Trace-ID`,
56
- - SDK logs share that `trace_id` so you can correlate SDK, backend, worker, and webhook activity,
57
- - sensitive fields such as API keys and tokens are redacted.
58
-
59
- ## Integration Path 1: Manual Capture (generic)
26
+ OpenAI:
60
27
 
61
28
  ```ts
62
- import { buildEvent, createClient } from "@rheonic/sdk";
29
+ import OpenAI from "openai";
30
+ import { createClient, instrumentOpenAI, RHEONICBlockedError } from "@rheonic/sdk";
63
31
 
64
- const client = createClient({
32
+ const rheonic = createClient({
65
33
  baseUrl: process.env.RHEONIC_BASE_URL!,
66
34
  ingestKey: process.env.RHEONIC_INGEST_KEY!,
67
35
  });
68
36
 
69
- await client.captureEvent(
70
- buildEvent({
71
- provider: "openai",
72
- model: "gpt-4o-mini",
73
- request: { endpoint: "/chat", input_tokens: 12 },
74
- response: { total_tokens: 32, latency_ms: 140, http_status: 200 },
75
- }),
76
- );
77
- ```
78
-
79
- Initialize `client` once during app startup, then reuse that same instance for manual capture and provider instrumentation.
80
-
81
- Minimal protect preflight usage:
82
-
83
- ```ts
84
- const decision = await client.protect({
85
- provider: "openai",
86
- model: "gpt-4o-mini",
37
+ const openai = instrumentOpenAI(new OpenAI({ apiKey: process.env.OPENAI_API_KEY! }), {
38
+ client: rheonic,
39
+ endpoint: "/chat/completions",
87
40
  feature: "assistant",
88
- inputTokensEstimate: 32,
89
- maxOutputTokens: 256,
90
41
  });
42
+
43
+ try {
44
+ await openai.chat.completions.create({
45
+ model: "gpt-4o-mini",
46
+ messages: [{ role: "user", content: "hello" }],
47
+ max_tokens: 256,
48
+ });
49
+ } catch (error) {
50
+ if (error instanceof RHEONICBlockedError) {
51
+ console.log("Blocked by protect preflight");
52
+ }
53
+ }
91
54
  ```
92
55
 
93
- ## Integration Path 2: OpenAI instrumentation (convenience wrapper)
56
+ Anthropic:
94
57
 
95
58
  ```ts
96
- import OpenAI from "openai";
97
- import { createClient, instrumentOpenAI } from "rheonic-node";
59
+ import Anthropic from "@anthropic-ai/sdk";
60
+ import { createClient, RHEONICBlockedError } from "@rheonic/sdk";
98
61
 
99
- const rheonicClient = createClient({
62
+ const rheonic = createClient({
100
63
  baseUrl: process.env.RHEONIC_BASE_URL!,
101
64
  ingestKey: process.env.RHEONIC_INGEST_KEY!,
102
65
  });
103
- const openai = instrumentOpenAI(new OpenAI({ apiKey: process.env.OPENAI_API_KEY }), {
104
- client: rheonicClient,
105
- endpoint: "/chat/completions",
106
- feature: "assistant",
107
- });
66
+
67
+ const anthropic = rheonic.instrumentAnthropic(new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY! }));
68
+
69
+ try {
70
+ await anthropic.messages.create({
71
+ model: "claude-3-5-sonnet-latest",
72
+ max_tokens: 256,
73
+ messages: [{ role: "user", content: "hello" }],
74
+ });
75
+ } catch (error) {
76
+ if (error instanceof RHEONICBlockedError) {
77
+ console.log("Blocked by protect preflight");
78
+ }
79
+ }
108
80
  ```
109
81
 
110
- ## Integration Path 3: Anthropic and Google wrappers
82
+ Google:
111
83
 
112
84
  ```ts
113
- import Anthropic from "@anthropic-ai/sdk";
114
85
  import { GoogleGenerativeAI } from "@google/generative-ai";
115
- import { createClient } from "rheonic-node";
86
+ import { createClient, RHEONICBlockedError } from "@rheonic/sdk";
116
87
 
117
- const client = createClient({
88
+ const rheonic = createClient({
118
89
  baseUrl: process.env.RHEONIC_BASE_URL!,
119
90
  ingestKey: process.env.RHEONIC_INGEST_KEY!,
120
91
  });
121
92
 
122
- const anthropic = client.instrumentAnthropic(new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }));
123
- await anthropic.messages.create({
124
- model: "claude-3-5-sonnet-latest",
125
- max_tokens: 256,
126
- messages: [{ role: "user", content: "Hello Claude" }],
127
- });
128
-
129
93
  const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY!);
130
- const googleModel = client.instrumentGoogle(genAI.getGenerativeModel({ model: "gemini-1.5-pro" }));
131
- await googleModel.generateContent("Hello Google model");
94
+ const model = rheonic.instrumentGoogle(genAI.getGenerativeModel({ model: "gemini-1.5-pro" }));
95
+
96
+ try {
97
+ await model.generateContent("hello");
98
+ } catch (error) {
99
+ if (error instanceof RHEONICBlockedError) {
100
+ console.log("Blocked by protect preflight");
101
+ }
102
+ }
132
103
  ```
133
104
 
134
- Runtime call path:
135
- - SDK instrumentation calls `POST /api/v1/protect/decision` then `POST /api/v1/events`.
136
- - Project mode in dashboard controls decision behavior:
137
- - Observe: allow only.
138
- - Protect: allow/warn/block with cooldown.
105
+ Keep one long-lived SDK client per app process. Initialize it during app startup and reuse it for all capture and instrumentation calls so Rheonic can avoid repeated protect cold-start latency.
139
106
 
140
- ## Provider SDKs
107
+ ## Optional: custom event capture
141
108
 
142
- Install only the provider SDKs you actually use alongside `rheonic-node`:
109
+ Use this only if you can't instrument a provider SDK or need custom events.
143
110
 
144
- ```bash
145
- npm install openai
146
- npm install @anthropic-ai/sdk
147
- npm install @google/generative-ai
111
+ ```ts
112
+ import { createClient, buildEvent } from "@rheonic/sdk";
113
+
114
+ const client = createClient({
115
+ baseUrl: process.env.RHEONIC_BASE_URL!,
116
+ ingestKey: process.env.RHEONIC_INGEST_KEY!,
117
+ });
118
+
119
+ await client.captureEvent(
120
+ buildEvent({
121
+ provider: "openai",
122
+ model: "gpt-4o-mini",
123
+ request: { endpoint: "/chat/completions", feature: "assistant" },
124
+ response: { total_tokens: 64, latency_ms: 120, http_status: 200 },
125
+ }),
126
+ );
148
127
  ```
149
128
 
150
- Beta prereleases use semver prerelease format such as `0.2.0-beta.1` and are published under the `next` tag.
129
+ ## Reference
130
+
131
+ Full quickstart:
132
+ - `https://beta.rheonic.dev/quickstart`
package/dist/client.js CHANGED
@@ -30,7 +30,13 @@ export class Client {
30
30
  constructor(config) {
31
31
  this.baseUrl = config.baseUrl ?? process.env.RHEONIC_BASE_URL ?? sdkNodeConfig.defaultBaseUrl;
32
32
  this.ingestKey = config.ingestKey;
33
- this.environment = config.environment ?? sdkNodeConfig.defaultEnvironment;
33
+ this.environment =
34
+ config.environment ??
35
+ process.env.NODE_ENV ??
36
+ process.env.APP_ENV ??
37
+ process.env.ENVIRONMENT ??
38
+ process.env.ENV ??
39
+ sdkNodeConfig.defaultEnvironment;
34
40
  this.flushIntervalMs = config.flushIntervalMs ?? sdkNodeConfig.defaultFlushIntervalMs;
35
41
  this.maxQueueSize = config.maxQueueSize ?? sdkNodeConfig.defaultMaxQueueSize;
36
42
  this.overflowPolicy = config.overflowPolicy ?? "drop_oldest";
package/dist/config.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  export declare const sdkNodeConfig: {
2
2
  readonly defaultBaseUrl: "http://localhost:8000";
3
- readonly defaultEnvironment: "dev";
3
+ readonly defaultEnvironment: "unknown";
4
4
  readonly defaultFlushIntervalMs: 1000;
5
5
  readonly defaultMaxQueueSize: 1000;
6
6
  readonly defaultFlushTimeoutMs: 500;
7
7
  readonly defaultRequestTimeoutMs: 1000;
8
8
  readonly defaultProtectFailMode: "open";
9
- readonly internalProtectDecisionTimeoutMs: 150;
9
+ readonly internalProtectDecisionTimeoutMs: 160;
10
10
  readonly retryDelayMinMs: 200;
11
11
  readonly retryDelayMaxMs: 400;
12
12
  readonly defaultTokenizerEncoding: "cl100k_base";
package/dist/config.js CHANGED
@@ -1,12 +1,12 @@
1
1
  export const sdkNodeConfig = {
2
2
  defaultBaseUrl: "http://localhost:8000",
3
- defaultEnvironment: "dev",
3
+ defaultEnvironment: "unknown",
4
4
  defaultFlushIntervalMs: 1000,
5
5
  defaultMaxQueueSize: 1000,
6
6
  defaultFlushTimeoutMs: 500,
7
7
  defaultRequestTimeoutMs: 1000,
8
8
  defaultProtectFailMode: "open",
9
- internalProtectDecisionTimeoutMs: 150,
9
+ internalProtectDecisionTimeoutMs: 160,
10
10
  retryDelayMinMs: 200,
11
11
  retryDelayMaxMs: 400,
12
12
  defaultTokenizerEncoding: "cl100k_base",
package/dist/logger.js CHANGED
@@ -23,7 +23,12 @@ export function emitLog(params) {
23
23
  timestamp: new Date().toISOString(),
24
24
  level: params.level,
25
25
  service: SERVICE_NAME,
26
- env: (params.environment ?? process.env.RHEONIC_ENV ?? process.env.NODE_ENV ?? "dev").toLowerCase(),
26
+ env: (params.environment ??
27
+ process.env.NODE_ENV ??
28
+ process.env.APP_ENV ??
29
+ process.env.ENVIRONMENT ??
30
+ process.env.ENV ??
31
+ "unknown").toLowerCase(),
27
32
  trace_id: params.traceId ?? getTraceId(),
28
33
  span_id: params.spanId ?? getSpanId(),
29
34
  event: sanitizeEvent(params.event),
@@ -45,4 +45,4 @@ export declare class ProtectEngine {
45
45
  private reportDecisionTimeout;
46
46
  private reportDecisionUnavailable;
47
47
  }
48
- export declare const defaultProtectTimeoutMs: 150;
48
+ export declare const defaultProtectTimeoutMs: 160;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rheonic/sdk",
3
- "version": "0.1.0-beta.2",
3
+ "version": "0.1.0-beta.4",
4
4
  "description": "Node.js SDK for Rheonic observability and protect preflight enforcement.",
5
5
  "author": "Rheonic <founder@rheonic.dev>",
6
6
  "license": "MIT",