@glassflow-ai/rius 0.5.0 → 0.6.1

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/dist/index.d.cts CHANGED
@@ -118,6 +118,7 @@ interface InitOptions extends RiusOptions {
118
118
  declare class RiusClient {
119
119
  private readonly provider;
120
120
  private readonly health?;
121
+ private readonly teardown;
121
122
  /** Resolves with the names of the auto-instrumentations that attached. */
122
123
  readonly ready: Promise<string[]>;
123
124
  private constructor();
@@ -145,9 +146,10 @@ declare class RiusClient {
145
146
  * {@link RiusClient.ready} if instrumentation must be attached before your
146
147
  * first span.
147
148
  *
148
- * The SDK installs no process exit hook: short-lived processes must call
149
+ * The SDK installs no exit hook for SPANS: short-lived processes must call
149
150
  * {@link RiusClient.flush} before exiting or spans still in the batch queue
150
- * are lost.
151
+ * are lost. (The heartbeat does register a `beforeExit` listener, only to
152
+ * send its final `stopped` ping; it flushes nothing.)
151
153
  */
152
154
  declare function init(options?: InitOptions): RiusClient;
153
155
  /** The SDK tracer. Scope name is wire-visible; do not parameterize it. */
@@ -170,6 +172,21 @@ declare enum SpanKind {
170
172
  interface SpanOptions {
171
173
  kind?: SpanKind;
172
174
  input?: unknown;
175
+ /**
176
+ * End-user identity (`user.id`). Sugar for `withUser`: set on this span at
177
+ * creation and, for the scoped variant, on every span opened inside it.
178
+ * To attribute a whole request, including auto-instrumented spans, prefer
179
+ * `withUser` around the handler.
180
+ */
181
+ userId?: string;
182
+ /**
183
+ * Identity attributes to set at span CREATION rather than after it. Pending
184
+ * snapshots are built at start, so anything a caller would otherwise
185
+ * `setAttribute` first thing (a tool name, say) belongs here to reach them.
186
+ * Content never does: it is not known at start and would bypass masking's
187
+ * assumptions about where content lives.
188
+ */
189
+ attributes?: Record<string, string>;
173
190
  }
174
191
  /** A handle over a span. Chainable setters; `end()` is idempotent. */
175
192
  declare class Observation {
@@ -178,6 +195,12 @@ declare class Observation {
178
195
  constructor(span: Span);
179
196
  setInput(value: unknown): this;
180
197
  setOutput(value: unknown): this;
198
+ /**
199
+ * Set an arbitrary attribute. Primitives and homogeneous primitive arrays
200
+ * are passed through as the OTel values they are; objects are JSON-encoded
201
+ * and bounded; `undefined` and `null` set nothing, since "no value" is not
202
+ * an empty string.
203
+ */
181
204
  setAttribute(key: string, value: unknown): this;
182
205
  /**
183
206
  * Record an error on the span and set ERROR status. This is exactly what the
@@ -231,6 +254,22 @@ interface GenerationOptions {
231
254
  * `gen_ai.request.reasoning_level`, which is not the convention's name.
232
255
  */
233
256
  reasoningLevel?: string;
257
+ /**
258
+ * The request's tool/function definitions, recorded immediately via
259
+ * {@link Generation.setToolDefinitions} — verbatim, any provider shape.
260
+ */
261
+ tools?: unknown[];
262
+ /**
263
+ * End-user identity (`user.id`). Sugar for `withUser`: set on this span at
264
+ * creation and, for the scoped variant, on every span opened inside it.
265
+ */
266
+ userId?: string;
267
+ /**
268
+ * Operation name (`gen_ai.operation.name`); default `"chat"`. Set it for
269
+ * `text_completion`, `embeddings` or `generate_content` calls, as the
270
+ * Python SDK's `operation=` allows.
271
+ */
272
+ operation?: string;
234
273
  }
235
274
  /** An LLM call. Content uses gen_ai message keys, never input.value. */
236
275
  declare class Generation extends Observation {
@@ -241,8 +280,24 @@ declare class Generation extends Observation {
241
280
  * in {@link setUsage}. A bare `new Generation(span)` has none and never sums.
242
281
  */
243
282
  constructor(span: ConstructorParameters<typeof Observation>[0], provider?: string | undefined);
283
+ /**
284
+ * Record the request messages (`gen_ai.input.messages`), normalised to the
285
+ * GenAI `{role, parts}` shape like the Python SDK does: bare strings, OpenAI
286
+ * dicts (including `tool_calls` and tool responses) and multimodal content
287
+ * lists are all accepted. Bare strings default to the `user` role.
288
+ */
244
289
  setInput(value: unknown): this;
290
+ /** Record the response messages (`gen_ai.output.messages`); bare strings default to `assistant`. */
245
291
  setOutput(value: unknown): this;
292
+ /**
293
+ * The request's tool/function definitions (`gen_ai.tool.definitions`).
294
+ * Serialized verbatim, in whatever shape the provider request used (OpenAI
295
+ * nests each tool under `function`, Anthropic uses top-level
296
+ * `name`/`input_schema`) — no normalization, so what is recorded is exactly
297
+ * what the model was shown. Definitions are content, not identity: they are
298
+ * masked/stripped under `captureContent: false` like messages are.
299
+ */
300
+ setToolDefinitions(tools: unknown[]): this;
246
301
  setModel(model: string): this;
247
302
  /**
248
303
  * Token usage (`gen_ai.usage.*`). Pass provider-reported values as-is;
@@ -307,8 +362,10 @@ interface ObserveOptions {
307
362
  captureOutput?: boolean;
308
363
  }
309
364
  /**
310
- * Wrap a function so each call becomes a span. Returns a function with the
311
- * same signature, so call sites and types are unchanged.
365
+ * Wrap a function so each call becomes a span. The returned function takes
366
+ * the same parameters and always returns a Promise of the original's result
367
+ * (a synchronous function becomes asynchronous), so call sites need an
368
+ * `await` but no other change.
312
369
  *
313
370
  * A wrapper rather than a decorator on purpose: TypeScript decorators apply
314
371
  * only to class members, and most agent code is plain functions.
@@ -339,6 +396,51 @@ declare function observe<F extends (...args: never[]) => unknown>(fn: F, options
339
396
  declare function withSession<T>(fn: (sessionId: string) => T): T;
340
397
  declare function withSession<T>(sessionId: string, fn: (sessionId: string) => T): T;
341
398
 
342
- declare const VERSION = "0.5.0";
399
+ /**
400
+ * Users: attribute every span of a request to the end user it served.
401
+ *
402
+ * The caller supplies the id (`withUser` for a scope) and `UserSpanProcessor`
403
+ * stamps it as the `user.id` attribute on every span started in scope. That
404
+ * key is the one OpenInference defines, Langfuse reads natively, and the
405
+ * OpenTelemetry registry lists; the sink also accepts OTel's `enduser.id`
406
+ * from third-party instrumentors, but this SDK emits one name for one fact.
407
+ *
408
+ * Stamping happens in `onStart`, as for sessions: the sink derives its user
409
+ * column per span, and pending snapshots are built at span start from the
410
+ * identity allowlist, so an attribute set later would reach neither.
411
+ *
412
+ * Two deliberate differences from `withSession`:
413
+ *
414
+ * - No process-wide default and no environment variable. A user is a
415
+ * property of a request, and a global default would attribute every
416
+ * request a process ever handles to one person.
417
+ * - Nothing is minted when the caller passes nothing. A session without an
418
+ * id is still a session; a span without a user is simply anonymous, and
419
+ * the backend treats an empty user id as exactly that.
420
+ *
421
+ * The id rides OTel context, so scopes nest, unwind with the callback even
422
+ * on a throw, and follow async continuations the same way the active span
423
+ * does.
424
+ */
425
+
426
+ /**
427
+ * Scope every span started inside `fn` to one end user.
428
+ *
429
+ * Pass the application's own identifier for the person the request serves.
430
+ * Prefer an opaque id over an email: it is stored on every span and shown
431
+ * in the console. When only sensitive identifiers exist, hash them first
432
+ * (OTel's `user.hash` / `enduser.pseudo.id` guidance). Nested scopes
433
+ * override outer ones. The id is passed to the callback so it can be logged
434
+ * alongside the work.
435
+ *
436
+ * ```typescript
437
+ * await withUser(request.userId, async () => {
438
+ * await handle(request) // every span of the request carries user.id
439
+ * })
440
+ * ```
441
+ */
442
+ declare function withUser<T>(userId: string, fn: (userId: string) => T): T;
443
+
444
+ declare const VERSION = "0.6.1";
343
445
 
344
- export { Generation, type GenerationBody, type GenerationOptions, type InitOptions, type Mask, Observation, type ObserveOptions, RiusClient, type RiusOptions, type SpanBody, SpanKind, type SpanOptions, VERSION, type WorkspaceExporterFactory, getTracer, init, observe, registerWorkspace, startAsCurrentGeneration, startAsCurrentSpan, startGeneration, startSpan, withSession, withWorkspace };
446
+ export { Generation, type GenerationBody, type GenerationOptions, type InitOptions, type Mask, Observation, type ObserveOptions, RiusClient, type RiusOptions, type SpanBody, SpanKind, type SpanOptions, VERSION, type WorkspaceExporterFactory, getTracer, init, observe, registerWorkspace, startAsCurrentGeneration, startAsCurrentSpan, startGeneration, startSpan, withSession, withUser, withWorkspace };
package/dist/index.d.ts CHANGED
@@ -118,6 +118,7 @@ interface InitOptions extends RiusOptions {
118
118
  declare class RiusClient {
119
119
  private readonly provider;
120
120
  private readonly health?;
121
+ private readonly teardown;
121
122
  /** Resolves with the names of the auto-instrumentations that attached. */
122
123
  readonly ready: Promise<string[]>;
123
124
  private constructor();
@@ -145,9 +146,10 @@ declare class RiusClient {
145
146
  * {@link RiusClient.ready} if instrumentation must be attached before your
146
147
  * first span.
147
148
  *
148
- * The SDK installs no process exit hook: short-lived processes must call
149
+ * The SDK installs no exit hook for SPANS: short-lived processes must call
149
150
  * {@link RiusClient.flush} before exiting or spans still in the batch queue
150
- * are lost.
151
+ * are lost. (The heartbeat does register a `beforeExit` listener, only to
152
+ * send its final `stopped` ping; it flushes nothing.)
151
153
  */
152
154
  declare function init(options?: InitOptions): RiusClient;
153
155
  /** The SDK tracer. Scope name is wire-visible; do not parameterize it. */
@@ -170,6 +172,21 @@ declare enum SpanKind {
170
172
  interface SpanOptions {
171
173
  kind?: SpanKind;
172
174
  input?: unknown;
175
+ /**
176
+ * End-user identity (`user.id`). Sugar for `withUser`: set on this span at
177
+ * creation and, for the scoped variant, on every span opened inside it.
178
+ * To attribute a whole request, including auto-instrumented spans, prefer
179
+ * `withUser` around the handler.
180
+ */
181
+ userId?: string;
182
+ /**
183
+ * Identity attributes to set at span CREATION rather than after it. Pending
184
+ * snapshots are built at start, so anything a caller would otherwise
185
+ * `setAttribute` first thing (a tool name, say) belongs here to reach them.
186
+ * Content never does: it is not known at start and would bypass masking's
187
+ * assumptions about where content lives.
188
+ */
189
+ attributes?: Record<string, string>;
173
190
  }
174
191
  /** A handle over a span. Chainable setters; `end()` is idempotent. */
175
192
  declare class Observation {
@@ -178,6 +195,12 @@ declare class Observation {
178
195
  constructor(span: Span);
179
196
  setInput(value: unknown): this;
180
197
  setOutput(value: unknown): this;
198
+ /**
199
+ * Set an arbitrary attribute. Primitives and homogeneous primitive arrays
200
+ * are passed through as the OTel values they are; objects are JSON-encoded
201
+ * and bounded; `undefined` and `null` set nothing, since "no value" is not
202
+ * an empty string.
203
+ */
181
204
  setAttribute(key: string, value: unknown): this;
182
205
  /**
183
206
  * Record an error on the span and set ERROR status. This is exactly what the
@@ -231,6 +254,22 @@ interface GenerationOptions {
231
254
  * `gen_ai.request.reasoning_level`, which is not the convention's name.
232
255
  */
233
256
  reasoningLevel?: string;
257
+ /**
258
+ * The request's tool/function definitions, recorded immediately via
259
+ * {@link Generation.setToolDefinitions} — verbatim, any provider shape.
260
+ */
261
+ tools?: unknown[];
262
+ /**
263
+ * End-user identity (`user.id`). Sugar for `withUser`: set on this span at
264
+ * creation and, for the scoped variant, on every span opened inside it.
265
+ */
266
+ userId?: string;
267
+ /**
268
+ * Operation name (`gen_ai.operation.name`); default `"chat"`. Set it for
269
+ * `text_completion`, `embeddings` or `generate_content` calls, as the
270
+ * Python SDK's `operation=` allows.
271
+ */
272
+ operation?: string;
234
273
  }
235
274
  /** An LLM call. Content uses gen_ai message keys, never input.value. */
236
275
  declare class Generation extends Observation {
@@ -241,8 +280,24 @@ declare class Generation extends Observation {
241
280
  * in {@link setUsage}. A bare `new Generation(span)` has none and never sums.
242
281
  */
243
282
  constructor(span: ConstructorParameters<typeof Observation>[0], provider?: string | undefined);
283
+ /**
284
+ * Record the request messages (`gen_ai.input.messages`), normalised to the
285
+ * GenAI `{role, parts}` shape like the Python SDK does: bare strings, OpenAI
286
+ * dicts (including `tool_calls` and tool responses) and multimodal content
287
+ * lists are all accepted. Bare strings default to the `user` role.
288
+ */
244
289
  setInput(value: unknown): this;
290
+ /** Record the response messages (`gen_ai.output.messages`); bare strings default to `assistant`. */
245
291
  setOutput(value: unknown): this;
292
+ /**
293
+ * The request's tool/function definitions (`gen_ai.tool.definitions`).
294
+ * Serialized verbatim, in whatever shape the provider request used (OpenAI
295
+ * nests each tool under `function`, Anthropic uses top-level
296
+ * `name`/`input_schema`) — no normalization, so what is recorded is exactly
297
+ * what the model was shown. Definitions are content, not identity: they are
298
+ * masked/stripped under `captureContent: false` like messages are.
299
+ */
300
+ setToolDefinitions(tools: unknown[]): this;
246
301
  setModel(model: string): this;
247
302
  /**
248
303
  * Token usage (`gen_ai.usage.*`). Pass provider-reported values as-is;
@@ -307,8 +362,10 @@ interface ObserveOptions {
307
362
  captureOutput?: boolean;
308
363
  }
309
364
  /**
310
- * Wrap a function so each call becomes a span. Returns a function with the
311
- * same signature, so call sites and types are unchanged.
365
+ * Wrap a function so each call becomes a span. The returned function takes
366
+ * the same parameters and always returns a Promise of the original's result
367
+ * (a synchronous function becomes asynchronous), so call sites need an
368
+ * `await` but no other change.
312
369
  *
313
370
  * A wrapper rather than a decorator on purpose: TypeScript decorators apply
314
371
  * only to class members, and most agent code is plain functions.
@@ -339,6 +396,51 @@ declare function observe<F extends (...args: never[]) => unknown>(fn: F, options
339
396
  declare function withSession<T>(fn: (sessionId: string) => T): T;
340
397
  declare function withSession<T>(sessionId: string, fn: (sessionId: string) => T): T;
341
398
 
342
- declare const VERSION = "0.5.0";
399
+ /**
400
+ * Users: attribute every span of a request to the end user it served.
401
+ *
402
+ * The caller supplies the id (`withUser` for a scope) and `UserSpanProcessor`
403
+ * stamps it as the `user.id` attribute on every span started in scope. That
404
+ * key is the one OpenInference defines, Langfuse reads natively, and the
405
+ * OpenTelemetry registry lists; the sink also accepts OTel's `enduser.id`
406
+ * from third-party instrumentors, but this SDK emits one name for one fact.
407
+ *
408
+ * Stamping happens in `onStart`, as for sessions: the sink derives its user
409
+ * column per span, and pending snapshots are built at span start from the
410
+ * identity allowlist, so an attribute set later would reach neither.
411
+ *
412
+ * Two deliberate differences from `withSession`:
413
+ *
414
+ * - No process-wide default and no environment variable. A user is a
415
+ * property of a request, and a global default would attribute every
416
+ * request a process ever handles to one person.
417
+ * - Nothing is minted when the caller passes nothing. A session without an
418
+ * id is still a session; a span without a user is simply anonymous, and
419
+ * the backend treats an empty user id as exactly that.
420
+ *
421
+ * The id rides OTel context, so scopes nest, unwind with the callback even
422
+ * on a throw, and follow async continuations the same way the active span
423
+ * does.
424
+ */
425
+
426
+ /**
427
+ * Scope every span started inside `fn` to one end user.
428
+ *
429
+ * Pass the application's own identifier for the person the request serves.
430
+ * Prefer an opaque id over an email: it is stored on every span and shown
431
+ * in the console. When only sensitive identifiers exist, hash them first
432
+ * (OTel's `user.hash` / `enduser.pseudo.id` guidance). Nested scopes
433
+ * override outer ones. The id is passed to the callback so it can be logged
434
+ * alongside the work.
435
+ *
436
+ * ```typescript
437
+ * await withUser(request.userId, async () => {
438
+ * await handle(request) // every span of the request carries user.id
439
+ * })
440
+ * ```
441
+ */
442
+ declare function withUser<T>(userId: string, fn: (userId: string) => T): T;
443
+
444
+ declare const VERSION = "0.6.1";
343
445
 
344
- export { Generation, type GenerationBody, type GenerationOptions, type InitOptions, type Mask, Observation, type ObserveOptions, RiusClient, type RiusOptions, type SpanBody, SpanKind, type SpanOptions, VERSION, type WorkspaceExporterFactory, getTracer, init, observe, registerWorkspace, startAsCurrentGeneration, startAsCurrentSpan, startGeneration, startSpan, withSession, withWorkspace };
446
+ export { Generation, type GenerationBody, type GenerationOptions, type InitOptions, type Mask, Observation, type ObserveOptions, RiusClient, type RiusOptions, type SpanBody, SpanKind, type SpanOptions, VERSION, type WorkspaceExporterFactory, getTracer, init, observe, registerWorkspace, startAsCurrentGeneration, startAsCurrentSpan, startGeneration, startSpan, withSession, withUser, withWorkspace };