@hue-run/sdk 0.23.0 → 0.23.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/CLI.md CHANGED
@@ -42,7 +42,7 @@ project manifest are refused because managers can update ancestor locks; Python
42
42
  The generated `hue.setup.mjs` or `hue_setup.py` always selects `captureContent: false` /
43
43
  `capture_content=False`. For a supported application, setup installs the dependency and adds the
44
44
  managed import and middleware registration to the existing entrypoint; an unreferenced helper is
45
- not a completed integration. TypeScript uses `@hue-run/sdk@0.23.0`, `@opentelemetry/api@1.9.1` and
45
+ not a completed integration. TypeScript uses `@hue-run/sdk@0.23.1`, `@opentelemetry/api@1.9.1` and
46
46
  `@opentelemetry/context-async-hooks@2.11.0`; Python setup uses its separately tested package pin.
47
47
  Content capture requires an ordinary account-managed key and a later explicit application decision.
48
48
 
@@ -381,8 +381,8 @@ and Hue never receives or stores them. The command is part of the `hue` executab
381
381
  # LANGFUSE_PUBLIC_KEY=pk-lf-...
382
382
  # LANGFUSE_SECRET_KEY=sk-lf-...
383
383
  # LANGFUSE_BASE_URL=https://cloud.langfuse.com
384
- npx -y @hue-run/sdk@0.23.0 import langfuse --env-path .env.langfuse --from 2026-01-01 --dry-run
385
- npx -y @hue-run/sdk@0.23.0 import langfuse --env-path .env.langfuse --from 2026-01-01 --media
384
+ npx -y @hue-run/sdk@0.23.1 import langfuse --env-path .env.langfuse --from 2026-01-01 --dry-run
385
+ npx -y @hue-run/sdk@0.23.1 import langfuse --env-path .env.langfuse --from 2026-01-01 --media
386
386
  ```
387
387
 
388
388
  `LANGFUSE_PUBLIC_KEY` and `LANGFUSE_SECRET_KEY` come from the environment or `--env-path`
@@ -892,7 +892,7 @@ node packages/sdk-typescript/scripts/verify-package.mjs --artifacts-dir .artifac
892
892
  # Set project to an existing supported fixture; use the same directory on resume.
893
893
  project=/absolute/path/to/supported-fixture
894
894
  node packages/sdk-typescript/scripts/verify-setup-live.mjs \
895
- --archive .artifacts/typescript/hue-run-sdk-0.23.0.tgz \
895
+ --archive .artifacts/typescript/hue-run-sdk-0.23.1.tgz \
896
896
  --origin https://STAGING_ORIGIN \
897
897
  --project "$project" --command setup \
898
898
  --evidence .context/setup-staging-before-claim.json
@@ -903,7 +903,7 @@ the private local handoff and finish the real browser claim, then reconcile the
903
903
 
904
904
  ```sh
905
905
  node packages/sdk-typescript/scripts/verify-setup-live.mjs \
906
- --archive .artifacts/typescript/hue-run-sdk-0.23.0.tgz \
906
+ --archive .artifacts/typescript/hue-run-sdk-0.23.1.tgz \
907
907
  --origin https://STAGING_ORIGIN \
908
908
  --project "$project" --command claim \
909
909
  --evidence .context/setup-staging-after-claim.json
@@ -945,10 +945,10 @@ otherwise. Never hand the agent Hue-native tools (`context.tools`, `context.mcp`
945
945
  production agent lacks. Pin the SDK, so the agent's repository gains no dependency:
946
946
 
947
947
  ```sh
948
- npx -y @hue-run/sdk@0.23.0 eval --case "Refund an eligible charge" --command "node agent.js"
949
- npx -y @hue-run/sdk@0.23.0 eval --case https://app.hue.run/projects/demo/scenarios/<id> --command "python agent.py" --timeout 120 --baseline <run id>
950
- npx -y @hue-run/sdk@0.23.0 eval --set "Billing regressions" --scorer-version <id> --command "node agent.js" --save-version
951
- npx -y @hue-run/sdk@0.23.0 eval --worker --command "node agent.js" --agent-key support-agent --revision <new-agent-revision>
948
+ npx -y @hue-run/sdk@0.23.1 eval --case "Refund an eligible charge" --command "node agent.js"
949
+ npx -y @hue-run/sdk@0.23.1 eval --case https://app.hue.run/projects/demo/scenarios/<id> --command "python agent.py" --timeout 120 --baseline <run id>
950
+ npx -y @hue-run/sdk@0.23.1 eval --set "Billing regressions" --scorer-version <id> --command "node agent.js" --save-version
951
+ npx -y @hue-run/sdk@0.23.1 eval --worker --command "node agent.js" --agent-key support-agent --revision <new-agent-revision>
952
952
  ```
953
953
 
954
954
  One invocation creates one run holding every selected case; it prints the run URL
@@ -986,7 +986,7 @@ export default function runMyAgent(inputs: JsonValue, context: SimulationTargetC
986
986
  ```
987
987
 
988
988
  ```sh
989
- npx -y @hue-run/sdk@0.23.0 eval --case "Refund an eligible charge" ./hue-agent.ts --content
989
+ npx -y @hue-run/sdk@0.23.1 eval --case "Refund an eligible charge" ./hue-agent.ts --content
990
990
  ```
991
991
 
992
992
  `--scenario` remains an alias for `--case` for existing scripts. Pass one selection flag.
package/README.md CHANGED
@@ -552,8 +552,8 @@ the Langfuse project's own keys (`LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, a
552
552
  `HUE_API_KEY`:
553
553
 
554
554
  ```sh
555
- npx -y @hue-run/sdk@0.23.0 import langfuse --env-path .env.langfuse --from 2026-01-01 --dry-run
556
- npx -y @hue-run/sdk@0.23.0 import langfuse --env-path .env.langfuse --from 2026-01-01 --media
555
+ npx -y @hue-run/sdk@0.23.1 import langfuse --env-path .env.langfuse --from 2026-01-01 --dry-run
556
+ npx -y @hue-run/sdk@0.23.1 import langfuse --env-path .env.langfuse --from 2026-01-01 --media
557
557
  ```
558
558
 
559
559
  - It reads Langfuse Cloud and self-hosted v4 through the Observations API v2, and self-hosted v3
@@ -1325,7 +1325,7 @@ existing-provider flush callbacks and recovery. Local/CI runners remain availabl
1325
1325
 
1326
1326
  ## Serving safely
1327
1327
 
1328
- Use `createHueSafe(options)` for best-effort startup. Invalid initialization returns a disabled client that keeps your `onExportIssue` hook and records the reason as an instrumentation failure. Pass `enabled: false` to disable Hue without a key or a `captureContent` choice; disabled helpers still execute the application callback, and `inject()` keeps propagating the application's own trace context. `flushSafe({ timeoutMillis: 1000 })` and `shutdownSafe({ timeoutMillis: 1000 })` return `{ ok, timedOut, report }` without rejecting. Strict initialization, connection checks and `flush()` remain available for diagnostics; do not gate application readiness or responses on them.
1328
+ Use `createHueSafe(options)` for best-effort startup. Invalid initialization returns a disabled client that keeps your `onExportIssue` hook and records a fixed initialization-failure diagnostic without inspecting or exposing the original error. Pass `enabled: false` to disable Hue without a key or a `captureContent` choice; disabled helpers still execute the application callback, and `inject()` keeps propagating the application's own trace context. `flushSafe({ timeoutMillis: 1000 })` and `shutdownSafe({ timeoutMillis: 1000 })` return `{ ok, timedOut, report }` without rejecting. Strict initialization, connection checks and `flush()` remain available for diagnostics; do not gate application readiness or responses on them.
1329
1329
 
1330
1330
  Capture/serialization/redaction/provider failures omit unsafe telemetry, record failures, and preserve the original business result/error. Async diagnostic rejections are contained; diagnostics are rate-limited. The default `maxQueueBytes` is 8 MiB across traces/logs including in-flight work, alongside the existing record cap. `pendingBytes` is a current queue gauge; `droppedSpans`, `droppedLogs` and `instrumentationFailures` are cumulative failure counters; `uploadedValues` and `uploadFallbacks` count completed uploads and upload fallbacks for whole attributes, eligible binary or large text media, and opt-in `recordFile` uploads. Whole-attribute fallbacks refused at export keep a prefix; media fallbacks keep a digest; helper upload fallbacks keep the file event; a value whose upload failed after export keeps its entry as well. This is a telemetry budget, not a total process memory ceiling. A timeout bounds the caller and does not cancel a borrowed provider. Never retry the business operation to recover telemetry. See [production setup](https://docs.hue.run/sdks/typescript#production-setup).
1331
1331
 
package/dist/client.js CHANGED
@@ -370,6 +370,8 @@ export class HueClient {
370
370
  * provider and surface as `hue.mcp.provider` / `hue.mcp.surface`.
371
371
  */
372
372
  async tool(name, input, execute, options = {}) {
373
+ if (!this.enabled || this.closed)
374
+ return this.withSpan("execute_tool", () => execute());
373
375
  const attributes = {
374
376
  "gen_ai.operation.name": "execute_tool",
375
377
  "gen_ai.tool.name": name,
@@ -380,22 +382,25 @@ export class HueClient {
380
382
  // A blank or non-string label is omitted and counted; the tool call itself still runs.
381
383
  if (isLabel(value))
382
384
  attributes[key] = value;
383
- else if (this.enabled && !this.closed)
385
+ else
384
386
  this.instrumentationFailed();
385
387
  };
386
- stamp("gen_ai.tool.call.id", options.callId);
387
- stamp("mcp.server.name", options.mcp?.name);
388
- stamp("mcp.server.version", options.mcp?.version);
389
- stamp("hue.mcp.provider", options.mcp?.provider);
390
- stamp("hue.mcp.surface", options.mcp?.surface);
391
- if (this.enabled && !this.closed && this.captureContent) {
392
- try {
393
- if (options.endpoint !== undefined)
394
- Object.assign(attributes, toolEndpointAttributes(options.endpoint));
395
- }
396
- catch {
397
- this.instrumentationFailed();
398
- }
388
+ let spanOptions = { attributes };
389
+ try {
390
+ stamp("gen_ai.tool.call.id", options.callId);
391
+ stamp("mcp.server.name", options.mcp?.name);
392
+ stamp("mcp.server.version", options.mcp?.version);
393
+ stamp("hue.mcp.provider", options.mcp?.provider);
394
+ stamp("hue.mcp.surface", options.mcp?.surface);
395
+ if (this.captureContent && options.endpoint !== undefined)
396
+ Object.assign(attributes, toolEndpointAttributes(options.endpoint));
397
+ spanOptions = {
398
+ attributes,
399
+ ...(options.parentContext ? { parentContext: options.parentContext } : {}),
400
+ };
401
+ }
402
+ catch {
403
+ this.instrumentationFailed();
399
404
  }
400
405
  return this.withSpan(`execute_tool ${name}`, async ({ span }) => {
401
406
  this.setContent(span, "gen_ai.tool.call.arguments", input);
@@ -403,10 +408,7 @@ export class HueClient {
403
408
  if (result !== undefined)
404
409
  this.setContent(span, "gen_ai.tool.call.result", result);
405
410
  return result;
406
- }, {
407
- attributes,
408
- ...(options.parentContext ? { parentContext: options.parentContext } : {}),
409
- });
411
+ }, spanOptions);
410
412
  }
411
413
  /**
412
414
  * Runs `callback` as a sub-agent: inside an `invoke_agent {name}` span carrying
@@ -420,11 +422,27 @@ export class HueClient {
420
422
  * in `withSpan`. A blank or non-string name is recorded as `unknown` and counted.
421
423
  */
422
424
  async subagent(name, callback, options = {}) {
425
+ if (!this.enabled || this.closed)
426
+ return this.withSpan("invoke_agent", callback);
423
427
  let agent = name;
424
428
  if (!isLabel(name)) {
425
429
  agent = "unknown";
426
- if (this.enabled && !this.closed)
427
- this.instrumentationFailed();
430
+ this.instrumentationFailed();
431
+ }
432
+ let spanOptions = {};
433
+ try {
434
+ spanOptions = {
435
+ ...options,
436
+ attributes: {
437
+ ...options.attributes,
438
+ "gen_ai.operation.name": "invoke_agent",
439
+ "gen_ai.agent.name": agent,
440
+ "hue.agent.role": "subagent",
441
+ },
442
+ };
443
+ }
444
+ catch {
445
+ this.instrumentationFailed();
428
446
  }
429
447
  return this.withSpan(`invoke_agent ${agent}`, async (span) => {
430
448
  let outputSet = false;
@@ -438,15 +456,7 @@ export class HueClient {
438
456
  if (result !== undefined && !outputSet)
439
457
  span.setOutput(result);
440
458
  return result;
441
- }, {
442
- ...options,
443
- attributes: {
444
- ...options.attributes,
445
- "gen_ai.operation.name": "invoke_agent",
446
- "gen_ai.agent.name": agent,
447
- "hue.agent.role": "subagent",
448
- },
449
- });
459
+ }, spanOptions);
450
460
  }
451
461
  /**
452
462
  * Runs `callback` inside a GenAI client span for one direct provider call, named
@@ -458,24 +468,44 @@ export class HueClient {
458
468
  * recorded as `gen_ai.system_instructions` and `gen_ai.tool.definitions`, content like `input`.
459
469
  */
460
470
  async model(model, callback, options) {
461
- // A disabled or closed client creates no span, so invalid metadata is not an instrumentation
462
- // failure either; only an active client records it (matching the other helpers).
463
- const active = this.enabled && !this.closed;
471
+ if (!this.enabled || this.closed)
472
+ return this.withSpan("model", callback);
473
+ let prepared = { provider: "unknown" };
474
+ try {
475
+ prepared = {
476
+ operation: options?.operation,
477
+ provider: options?.provider,
478
+ name: options?.name,
479
+ sessionId: options?.sessionId,
480
+ userId: options?.userId,
481
+ workspaceId: options?.workspaceId,
482
+ parentContext: options?.parentContext,
483
+ ...(this.captureContent
484
+ ? {
485
+ input: options?.input,
486
+ systemInstructions: options?.systemInstructions,
487
+ tools: options?.tools,
488
+ }
489
+ : {}),
490
+ };
491
+ }
492
+ catch {
493
+ this.instrumentationFailed();
494
+ }
464
495
  const label = (value, fallback) => {
465
496
  if (isLabel(value))
466
497
  return value;
467
- if (active)
468
- this.instrumentationFailed();
498
+ this.instrumentationFailed();
469
499
  return fallback;
470
500
  };
471
501
  const requestModel = label(model, "unknown");
472
- const operation = label(options?.operation ?? "chat", "chat");
473
- const provider = label(options?.provider, "unknown");
474
- const name = options?.name === undefined
502
+ const operation = label(prepared.operation ?? "chat", "chat");
503
+ const provider = label(prepared.provider, "unknown");
504
+ const name = prepared.name === undefined
475
505
  ? `${operation} ${requestModel}`
476
- : label(options.name, `${operation} ${requestModel}`);
506
+ : label(prepared.name, `${operation} ${requestModel}`);
477
507
  const metadata = { operation, provider, requestModel };
478
- const { sessionId, userId, workspaceId, parentContext, input, systemInstructions, tools, } = options ?? {};
508
+ const { sessionId, userId, workspaceId, parentContext, input, systemInstructions, tools } = prepared;
479
509
  return this.withSpan(name, (span) => {
480
510
  const handle = {
481
511
  ...span,
@@ -507,22 +537,22 @@ export class HueClient {
507
537
  setUsage(span, usage) {
508
538
  if (!this.enabled || this.closed)
509
539
  return;
510
- for (const [key, value] of [
511
- ["gen_ai.usage.input_tokens", usage?.inputTokens],
512
- ["gen_ai.usage.output_tokens", usage?.outputTokens],
513
- ]) {
514
- if (value === undefined)
515
- continue;
516
- if (!Number.isInteger(value) || value < 0) {
517
- this.instrumentationFailed();
518
- continue;
519
- }
520
- try {
540
+ try {
541
+ for (const [key, value] of [
542
+ ["gen_ai.usage.input_tokens", usage?.inputTokens],
543
+ ["gen_ai.usage.output_tokens", usage?.outputTokens],
544
+ ]) {
545
+ if (value === undefined)
546
+ continue;
547
+ if (!Number.isInteger(value) || value < 0) {
548
+ this.instrumentationFailed();
549
+ continue;
550
+ }
521
551
  span.setAttribute(key, value);
522
552
  }
523
- catch {
524
- this.instrumentationFailed();
525
- }
553
+ }
554
+ catch {
555
+ this.instrumentationFailed();
526
556
  }
527
557
  }
528
558
  /**
@@ -1275,11 +1305,10 @@ export function createHueSafe(options) {
1275
1305
  try {
1276
1306
  return new HueClient(options);
1277
1307
  }
1278
- catch (error) {
1279
- // The caller's diagnostics hook stays attached and hears why telemetry is off.
1308
+ catch {
1309
+ // Provider errors can contain credentials or expose throwing message accessors.
1280
1310
  const disabled = new HueClient({ enabled: false, onExportIssue: issueCallback(options) });
1281
- const reason = error instanceof Error && error.message ? error.message : "unknown error";
1282
- disabled.transport.instrumentationFailure("traces", `Hue is disabled: ${reason.slice(0, 256)}`);
1311
+ disabled.transport.instrumentationFailure("traces", "Hue is disabled: initialization failed");
1283
1312
  return disabled;
1284
1313
  }
1285
1314
  }
package/dist/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /** Package version shared by the instrumentation scope and the export User-Agent. */
2
- export declare const sdkVersion = "0.23.0";
2
+ export declare const sdkVersion = "0.23.1";
3
3
  /** OTLP dependency version sent in the export User-Agent. */
4
4
  export declare const otlpExporterVersion = "0.223.0";
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Generated by scripts/write-version.mjs from package.json; do not edit by hand.
2
2
  /** Package version shared by the instrumentation scope and the export User-Agent. */
3
- export const sdkVersion = "0.23.0";
3
+ export const sdkVersion = "0.23.1";
4
4
  /** OTLP dependency version sent in the export User-Agent. */
5
5
  export const otlpExporterVersion = "0.223.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hue-run/sdk",
3
- "version": "0.23.0",
3
+ "version": "0.23.1",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "publishConfig": {