@hue-run/sdk 0.20.0 → 0.20.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.20.0`, `@opentelemetry/api@1.9.1` and
45
+ not a completed integration. TypeScript uses `@hue-run/sdk@0.20.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
 
@@ -379,8 +379,8 @@ and Hue never receives or stores them. The command is part of the `hue` executab
379
379
  # LANGFUSE_PUBLIC_KEY=pk-lf-...
380
380
  # LANGFUSE_SECRET_KEY=sk-lf-...
381
381
  # LANGFUSE_BASE_URL=https://cloud.langfuse.com
382
- npx -y @hue-run/sdk@0.20.0 import langfuse --env-path .env.langfuse --from 2026-01-01 --dry-run
383
- npx -y @hue-run/sdk@0.20.0 import langfuse --env-path .env.langfuse --from 2026-01-01 --media
382
+ npx -y @hue-run/sdk@0.20.1 import langfuse --env-path .env.langfuse --from 2026-01-01 --dry-run
383
+ npx -y @hue-run/sdk@0.20.1 import langfuse --env-path .env.langfuse --from 2026-01-01 --media
384
384
  ```
385
385
 
386
386
  `LANGFUSE_PUBLIC_KEY` and `LANGFUSE_SECRET_KEY` come from the environment or `--env-path`
@@ -595,7 +595,7 @@ node packages/sdk-typescript/scripts/verify-package.mjs --artifacts-dir .artifac
595
595
  # Set project to an existing supported fixture; use the same directory on resume.
596
596
  project=/absolute/path/to/supported-fixture
597
597
  node packages/sdk-typescript/scripts/verify-setup-live.mjs \
598
- --archive .artifacts/typescript/hue-run-sdk-0.20.0.tgz \
598
+ --archive .artifacts/typescript/hue-run-sdk-0.20.1.tgz \
599
599
  --origin https://STAGING_ORIGIN \
600
600
  --project "$project" --command setup \
601
601
  --evidence .context/setup-staging-before-claim.json
@@ -606,7 +606,7 @@ the private local handoff and finish the real browser claim, then reconcile the
606
606
 
607
607
  ```sh
608
608
  node packages/sdk-typescript/scripts/verify-setup-live.mjs \
609
- --archive .artifacts/typescript/hue-run-sdk-0.20.0.tgz \
609
+ --archive .artifacts/typescript/hue-run-sdk-0.20.1.tgz \
610
610
  --origin https://STAGING_ORIGIN \
611
611
  --project "$project" --command claim \
612
612
  --evidence .context/setup-staging-after-claim.json
@@ -648,10 +648,10 @@ otherwise. Never hand the agent Hue-native tools (`context.tools`, `context.mcp`
648
648
  production agent lacks. Pin the SDK, so the agent's repository gains no dependency:
649
649
 
650
650
  ```sh
651
- npx -y @hue-run/sdk@0.20.0 eval --case "Refund an eligible charge" --command "node agent.js"
652
- npx -y @hue-run/sdk@0.20.0 eval --case https://app.hue.run/projects/demo/scenarios/<id> --command "python agent.py" --timeout 120 --baseline <run id>
653
- npx -y @hue-run/sdk@0.20.0 eval --set "Billing regressions" --scorer-version <id> --command "node agent.js" --save-version
654
- npx -y @hue-run/sdk@0.20.0 eval --worker --command "node agent.js" --agent-key support-agent --revision <new-agent-revision>
651
+ npx -y @hue-run/sdk@0.20.1 eval --case "Refund an eligible charge" --command "node agent.js"
652
+ npx -y @hue-run/sdk@0.20.1 eval --case https://app.hue.run/projects/demo/scenarios/<id> --command "python agent.py" --timeout 120 --baseline <run id>
653
+ npx -y @hue-run/sdk@0.20.1 eval --set "Billing regressions" --scorer-version <id> --command "node agent.js" --save-version
654
+ npx -y @hue-run/sdk@0.20.1 eval --worker --command "node agent.js" --agent-key support-agent --revision <new-agent-revision>
655
655
  ```
656
656
 
657
657
  One invocation creates one run holding every selected case; it prints the run URL
@@ -689,7 +689,7 @@ export default function runMyAgent(inputs: JsonValue, context: SimulationTargetC
689
689
  ```
690
690
 
691
691
  ```sh
692
- npx -y @hue-run/sdk@0.20.0 eval --case "Refund an eligible charge" ./hue-agent.ts --content
692
+ npx -y @hue-run/sdk@0.20.1 eval --case "Refund an eligible charge" ./hue-agent.ts --content
693
693
  ```
694
694
 
695
695
  `--scenario` remains an alias for `--case` for existing scripts. Pass one selection flag.
package/README.md CHANGED
@@ -536,8 +536,8 @@ the Langfuse project's own keys (`LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, a
536
536
  `HUE_API_KEY`:
537
537
 
538
538
  ```sh
539
- npx -y @hue-run/sdk@0.20.0 import langfuse --env-path .env.langfuse --from 2026-01-01 --dry-run
540
- npx -y @hue-run/sdk@0.20.0 import langfuse --env-path .env.langfuse --from 2026-01-01 --media
539
+ npx -y @hue-run/sdk@0.20.1 import langfuse --env-path .env.langfuse --from 2026-01-01 --dry-run
540
+ npx -y @hue-run/sdk@0.20.1 import langfuse --env-path .env.langfuse --from 2026-01-01 --media
541
541
  ```
542
542
 
543
543
  - It reads Langfuse Cloud and self-hosted v4 through the Observations API v2, and self-hosted v3
package/WORLDS.md CHANGED
@@ -13,8 +13,9 @@ Your agent runs in your process while a disposable simulated world runs in Hue.
13
13
  authoritative and records an ordered journal; Hue does not execute your agent code or provider
14
14
  credentials.
15
15
 
16
- A World is a reconstructed starting state. An instance is an isolated running copy of that
17
- state. Starting another instance does not share the first instance's changes. The handoff's
16
+ A World model is retained entity history. A World is a reconstructed starting state. A World
17
+ instance is an isolated running copy of that state. Starting another World instance does not
18
+ share the first World instance's changes. The handoff's
18
19
  legacy `worldId` field identifies the runtime instance, not a durable World model.
19
20
 
20
21
  ## Reconstruct a user's World
@@ -52,6 +53,14 @@ reports that the World is preparing. Retries preserve the same request bytes and
52
53
  Other failures keep the client's `maxAttempts` limit. Pass `{ signal }` as the last options
53
54
  argument to cancel a preparation wait or an active request.
54
55
 
56
+ When the service reports preparation progress, `worldModel.processing` distinguishes retained
57
+ evidence from indexed evidence. A start's `preparation` also includes the selected evidence
58
+ cutoff. `HueWorldError.preparation` exposes the same bounded progress on a preparation refusal.
59
+ Insufficient evidence and processing limits stop identical retries. Useful later evidence or an
60
+ interpreter update can prepare the same unfinished request automatically. Retrying its original
61
+ idempotency key starts the first usable World selected for that request. Preparation requires no
62
+ review or publish action.
63
+
55
64
  `listModels` and `listAccounts` accept `after` and `limit` for pagination. Use each account's
56
65
  `providerInstanceKey` to distinguish connections, including several accounts for one app.
57
66
 
@@ -112,7 +121,9 @@ OAuth tokens or provider credentials in these fields.
112
121
 
113
122
  ## Publish an authored World
114
123
 
115
- `createWorldClient` also publishes authored definitions and starts instances from their
124
+ `createWorldClient` uses `createWorld`, `listWorlds` and `getWorld` for World identities.
125
+ The compatibility names `createEnvironment`, `listEnvironments` and `getEnvironment` remain
126
+ available. The client also publishes authored definitions and starts World instances from their
116
127
  immutable versions. Use `WorldDefinitionV2` and `WorldProviderInstance` for arbitrary registered
117
128
  apps and multiple accounts of the same app. The deployment validates each app's JSON
118
129
  configuration and supported dialects.
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** Package version shared by the instrumentation scope and the export User-Agent. */
2
- export declare const sdkVersion = "0.20.0";
2
+ export declare const sdkVersion = "0.20.1";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
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.20.0";
3
+ export const sdkVersion = "0.20.1";
@@ -1,3 +1,4 @@
1
+ import { type WorldPreparationProgress } from "./readiness.js";
1
2
  import type { ActionInput, ActionResult, CoverageGapInput, CoverageGapResult, CreateRunInput, Environment, PublishableEnvironmentDefinition, EnvironmentIdentity, EnvironmentPage, EnvironmentPageOptions, EnvironmentRun, EnvironmentSummary, EnvironmentVersion, EnvironmentVersionSummary, FinishRunInput, SealedRun, StepPage, StepPageOptions, WorldEvidence, WorldEvidenceOptions } from "./types.js";
2
3
  import type { PublishableWorldDefinition, WorldVersion } from "./definitions.js";
3
4
  /** Connection and retry options for {@link createEnvironmentClient}. */
@@ -19,13 +20,17 @@ export declare class HueEnvironmentError extends Error {
19
20
  readonly retryAfterMs?: number | undefined;
20
21
  /** The server's `X-Hue-Diagnostic` code, when it is a short snake-case value. */
21
22
  readonly diagnostic?: string | undefined;
23
+ /** Bounded, sanitized progress for a World preparation refusal. */
24
+ readonly preparation?: WorldPreparationProgress | undefined;
22
25
  constructor(
23
26
  /** HTTP status when Hue answered; absent for transport, timeout or parse failure. */
24
27
  status?: number | undefined,
25
28
  /** Hue's `Retry-After` in milliseconds, bounded, when a 429 or 503 carried one. */
26
29
  retryAfterMs?: number | undefined,
27
30
  /** The server's `X-Hue-Diagnostic` code, when it is a short snake-case value. */
28
- diagnostic?: string | undefined);
31
+ diagnostic?: string | undefined,
32
+ /** Bounded, sanitized progress for a World preparation refusal. */
33
+ preparation?: WorldPreparationProgress | undefined);
29
34
  }
30
35
  /** Starts one isolated instance from an immutable World version. */
31
36
  export interface CreateInstanceInput extends Omit<CreateRunInput, "environmentVersionId"> {
@@ -34,7 +39,7 @@ export interface CreateInstanceInput extends Omit<CreateRunInput, "environmentVe
34
39
  }
35
40
  /** A connection failure or a status the client retries; seal polling continues through these. */
36
41
  export declare function isTransientEnvironmentError(error: unknown): boolean;
37
- /** Typed client for authored environments, isolated runs and immutable journals. */
42
+ /** Typed client for authored Worlds, isolated World instances and immutable journals. */
38
43
  export declare class WorldClient {
39
44
  #private;
40
45
  /** Validated Hue origin. */
@@ -79,6 +84,12 @@ export declare class WorldClient {
79
84
  }>;
80
85
  /** Completes or abandons one instance and freezes its evidence. */
81
86
  finishInstance(instanceId: string, input: FinishRunInput): Promise<SealedRun>;
87
+ /** Creates a World identity using the client's resource routes. */
88
+ createWorld(input: EnvironmentIdentity): Promise<EnvironmentSummary>;
89
+ /** Lists active Worlds. */
90
+ listWorlds(page?: EnvironmentPageOptions): Promise<EnvironmentPage>;
91
+ /** Reads a World and its immutable version summaries. */
92
+ getWorld(id: string): Promise<Environment>;
82
93
  /** Creates an environment identity; this non-idempotent registry write is not retried. */
83
94
  createEnvironment(input: EnvironmentIdentity): Promise<EnvironmentSummary>;
84
95
  /** Lists active environment identities. */
@@ -1,3 +1,4 @@
1
+ import { readWorldPreparation, TERMINAL_WORLD_DIAGNOSTICS, } from "./readiness.js";
1
2
  import { validateOptions } from "../config.js";
2
3
  import { aggregateBounds, json, uuid, valueBounds } from "../evals/json.js";
3
4
  /** Sanitized environment API failure that never includes response text or credentials. */
@@ -5,19 +6,23 @@ export class HueEnvironmentError extends Error {
5
6
  status;
6
7
  retryAfterMs;
7
8
  diagnostic;
9
+ preparation;
8
10
  constructor(
9
11
  /** HTTP status when Hue answered; absent for transport, timeout or parse failure. */
10
12
  status,
11
13
  /** Hue's `Retry-After` in milliseconds, bounded, when a 429 or 503 carried one. */
12
14
  retryAfterMs,
13
15
  /** The server's `X-Hue-Diagnostic` code, when it is a short snake-case value. */
14
- diagnostic) {
16
+ diagnostic,
17
+ /** Bounded, sanitized progress for a World preparation refusal. */
18
+ preparation) {
15
19
  super(status
16
20
  ? `Hue environment request failed (HTTP ${status}${diagnostic ? `, ${diagnostic}` : ""})`
17
21
  : "Hue environment connection or response failed");
18
22
  this.status = status;
19
23
  this.retryAfterMs = retryAfterMs;
20
24
  this.diagnostic = diagnostic;
25
+ this.preparation = preparation;
21
26
  this.name = "HueEnvironmentError";
22
27
  }
23
28
  }
@@ -31,7 +36,8 @@ const RETRYABLE = new Set([408, 429, 500, 502, 503, 504]);
31
36
  /** A connection failure or a status the client retries; seal polling continues through these. */
32
37
  export function isTransientEnvironmentError(error) {
33
38
  return (error instanceof HueEnvironmentError &&
34
- (error.status === undefined || RETRYABLE.has(error.status)));
39
+ (error.status === undefined || RETRYABLE.has(error.status)) &&
40
+ !(error.status === 503 && TERMINAL_WORLD_DIAGNOSTICS.has(error.diagnostic ?? "")));
35
41
  }
36
42
  /** A `Retry-After` longer than this waits this long: Hue asks for a second, never minutes. */
37
43
  const MAX_RETRY_AFTER_MS = 10_000;
@@ -59,7 +65,7 @@ const REQUEST_BOUNDS = { ...valueBounds, bytes: 1024 * 1024 };
59
65
  * definition without relaxing action/run request envelopes.
60
66
  */
61
67
  const ENVIRONMENT_PUBLICATION_BOUNDS = aggregateBounds(240_000 + 32);
62
- /** Typed client for authored environments, isolated runs and immutable journals. */
68
+ /** Typed client for authored Worlds, isolated World instances and immutable journals. */
63
69
  export class WorldClient {
64
70
  /** Validated Hue origin. */
65
71
  baseUrl;
@@ -106,8 +112,9 @@ export class WorldClient {
106
112
  throw new HueEnvironmentError();
107
113
  }
108
114
  if (!response.ok) {
109
- await response.body?.cancel();
110
- throw new HueEnvironmentError(response.status, response.status === 429 || response.status === 503 ? retryAfterMillis(response) : undefined, diagnosticOf(response));
115
+ const diagnostic = diagnosticOf(response);
116
+ const preparation = await readWorldPreparation(response, diagnostic);
117
+ throw new HueEnvironmentError(response.status, response.status === 429 || response.status === 503 ? retryAfterMillis(response) : undefined, diagnostic, preparation);
111
118
  }
112
119
  try {
113
120
  const reader = response.body?.getReader();
@@ -246,6 +253,18 @@ export class WorldClient {
246
253
  finishInstance(instanceId, input) {
247
254
  return this.finishRun(instanceId, input);
248
255
  }
256
+ /** Creates a World identity using the client's resource routes. */
257
+ createWorld(input) {
258
+ return this.createEnvironment(input);
259
+ }
260
+ /** Lists active Worlds. */
261
+ listWorlds(page) {
262
+ return this.listEnvironments(page);
263
+ }
264
+ /** Reads a World and its immutable version summaries. */
265
+ getWorld(id) {
266
+ return this.getEnvironment(id);
267
+ }
249
268
  /** Creates an environment identity; this non-idempotent registry write is not retried. */
250
269
  createEnvironment(input) {
251
270
  return this.requestOnce("POST", "/environments", input);
@@ -1,3 +1,5 @@
1
+ import type { WorldModelProcessing, WorldPreparationProgress } from "./readiness.js";
2
+ export type { WorldModelProcessing, WorldPreparationProgress } from "./readiness.js";
1
3
  /** Project-scoped identity of the user or entity represented by a World model. */
2
4
  export interface WorldEntity {
3
5
  /** Identifier namespace, such as the application's user namespace. */
@@ -21,8 +23,10 @@ export interface WorldModel {
21
23
  lastUsedAt: string | null;
22
24
  /** Committed evidence sequence used for reconstruction. */
23
25
  evidenceCutoff: number;
24
- /** Publication or erasure state. */
26
+ /** Legacy retention or erasure state. Read `processing` for current indexing progress. */
25
27
  status: "ready" | "preparing" | "erased";
28
+ /** Retained and indexed progress, when reported by Hue. */
29
+ processing?: WorldModelProcessing;
26
30
  }
27
31
  /** One app account bound to a World model. */
28
32
  export interface WorldModelAccount {
@@ -53,7 +57,7 @@ export interface StartingWorld {
53
57
  evidenceCutoff: number;
54
58
  /** Immutable starting-state digest, or null while preparation is incomplete. */
55
59
  digest: string | null;
56
- /** Publication or erasure state. */
60
+ /** Starting-state preparation status. */
57
61
  status: "ready" | "preparing";
58
62
  }
59
63
  /** Bounded pagination over World models or their accounts. */
@@ -109,6 +113,8 @@ export interface WorldModelResult {
109
113
  export interface StartingWorldResult {
110
114
  /** Immutable starting state, or an explicit preparing state. */
111
115
  world: StartingWorld;
116
+ /** Progress of this requested starting World, when reported by Hue. */
117
+ preparation?: WorldPreparationProgress;
112
118
  }
113
119
  /** Acknowledgement that the World model has been erased. */
114
120
  export interface ErasedWorldModel {
@@ -1,5 +1,5 @@
1
1
  import { WorldClient, type WorldClientOptions } from "./client.js";
2
- import type { CreateWorldModelInput, WorldModelResult, StartingWorldResult, ErasedWorldModel, ReproduceWorldInstanceInput, StartingWorld, StartWorldInstanceInput, WorldModelAccountPage, WorldModelPage, WorldModelPageOptions } from "./model-types.js";
2
+ import type { CreateWorldModelInput, WorldModelResult, StartingWorldResult, ErasedWorldModel, ReproduceWorldInstanceInput, StartingWorld, StartWorldInstanceInput, WorldModelAccountPage, WorldModelPage, WorldModelPageOptions, WorldPreparationProgress } from "./model-types.js";
3
3
  import type { WorldHandoff } from "./types.js";
4
4
  /** Reconstructed starting World and its isolated runtime connection. */
5
5
  export interface WorldInstanceResult {
@@ -7,6 +7,8 @@ export interface WorldInstanceResult {
7
7
  world: StartingWorld;
8
8
  /** Fresh, instance-scoped connection and credentials. */
9
9
  instance: WorldHandoff;
10
+ /** Progress of this requested starting World, when reported by Hue. */
11
+ preparation?: WorldPreparationProgress;
10
12
  }
11
13
  /** Project-key client for entity histories, reconstructed Worlds and isolated instances. */
12
14
  export declare class WorldModelClient extends WorldClient {
@@ -0,0 +1,18 @@
1
+ /** Progress of one requested starting World. */
2
+ export interface WorldPreparationProgress {
3
+ /** Whether the request is preparing, usable, or waiting for changed evidence or dependencies. */
4
+ state: "preparing" | "insufficient_evidence" | "processing_limit" | "dependency_unavailable" | "ready";
5
+ /** Evidence cutoff selected for this request. */
6
+ selectedEvidenceCutoff: number;
7
+ /** Latest retained evidence cutoff. */
8
+ retainedEvidenceCutoff: number;
9
+ /** Latest indexed evidence cutoff for the current interpretation. */
10
+ readyEvidenceCutoff: number;
11
+ /** Whether retained evidence is still waiting for indexing. */
12
+ pendingEvidence: boolean;
13
+ }
14
+ /** Retained and indexed progress of an entity history. */
15
+ export interface WorldModelProcessing extends Omit<WorldPreparationProgress, "state" | "selectedEvidenceCutoff"> {
16
+ /** Indexing progress; a requested represented time may still lack required evidence. */
17
+ state: "indexed" | "preparing" | "insufficient_evidence" | "processing_limit" | "dependency_unavailable";
18
+ }
@@ -0,0 +1,69 @@
1
+ const diagnosticStates = {
2
+ world_preparing: "preparing",
3
+ world_insufficient_evidence: "insufficient_evidence",
4
+ world_processing_limit: "processing_limit",
5
+ world_dependency_unavailable: "dependency_unavailable",
6
+ };
7
+ /** @internal Only numeric progress and an allowlisted state cross the error boundary. */
8
+ export async function readWorldPreparation(response, diagnostic) {
9
+ if (response.status !== 503 || diagnostic === undefined || !(diagnostic in diagnosticStates)) {
10
+ await response.body?.cancel().catch(() => { });
11
+ return undefined;
12
+ }
13
+ const reader = response.body?.getReader();
14
+ if (!reader)
15
+ return undefined;
16
+ try {
17
+ const chunks = [];
18
+ let size = 0;
19
+ for (;;) {
20
+ const { done, value } = await reader.read();
21
+ if (done)
22
+ break;
23
+ size += value.byteLength;
24
+ if (size > 16 * 1024)
25
+ return undefined;
26
+ chunks.push(value);
27
+ }
28
+ const body = JSON.parse(Buffer.concat(chunks).toString("utf8"));
29
+ if (!body || typeof body !== "object" || !("preparation" in body))
30
+ return undefined;
31
+ const value = body.preparation;
32
+ if (!value || typeof value !== "object")
33
+ return undefined;
34
+ const { state, selectedEvidenceCutoff: selected, retainedEvidenceCutoff: retained, readyEvidenceCutoff: ready, pendingEvidence, } = value;
35
+ const expectedState = diagnosticStates[diagnostic];
36
+ if (expectedState === undefined ||
37
+ state !== expectedState ||
38
+ !Number.isSafeInteger(selected) ||
39
+ !Number.isSafeInteger(retained) ||
40
+ !Number.isSafeInteger(ready) ||
41
+ typeof selected !== "number" ||
42
+ typeof retained !== "number" ||
43
+ typeof ready !== "number" ||
44
+ selected < 0 ||
45
+ ready < 0 ||
46
+ selected > retained ||
47
+ ready > retained ||
48
+ pendingEvidence !== retained > ready)
49
+ return undefined;
50
+ return {
51
+ state: expectedState,
52
+ selectedEvidenceCutoff: selected,
53
+ retainedEvidenceCutoff: retained,
54
+ readyEvidenceCutoff: ready,
55
+ pendingEvidence,
56
+ };
57
+ }
58
+ catch {
59
+ return undefined;
60
+ }
61
+ finally {
62
+ await reader.cancel().catch(() => { });
63
+ }
64
+ }
65
+ /** @internal These failures require changed evidence or processing, not another identical call. */
66
+ export const TERMINAL_WORLD_DIAGNOSTICS = new Set([
67
+ "world_insufficient_evidence",
68
+ "world_processing_limit",
69
+ ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hue-run/sdk",
3
- "version": "0.20.0",
3
+ "version": "0.20.1",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "publishConfig": {