@hue-run/sdk 0.13.1 → 0.13.2
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 +27 -12
- package/EVALUATIONS.md +8 -1
- package/README.md +5 -3
- package/dist/cli/eval.js +31 -5
- package/dist/evals/client.d.ts +1 -1
- package/dist/evals/client.js +1 -1
- package/dist/evals/scorer-publication.js +7 -2
- package/dist/evals/types.d.ts +19 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
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.13.
|
|
45
|
+
not a completed integration. TypeScript uses `@hue-run/sdk@0.13.2`, `@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
|
|
|
@@ -469,7 +469,7 @@ node packages/sdk-typescript/scripts/verify-package.mjs --artifacts-dir .artifac
|
|
|
469
469
|
# Set project to an existing supported fixture; use the same directory on resume.
|
|
470
470
|
project=/absolute/path/to/supported-fixture
|
|
471
471
|
node packages/sdk-typescript/scripts/verify-setup-live.mjs \
|
|
472
|
-
--archive .artifacts/typescript/hue-run-sdk-0.13.
|
|
472
|
+
--archive .artifacts/typescript/hue-run-sdk-0.13.2.tgz \
|
|
473
473
|
--origin https://STAGING_ORIGIN \
|
|
474
474
|
--project "$project" --command setup \
|
|
475
475
|
--evidence .context/setup-staging-before-claim.json
|
|
@@ -480,7 +480,7 @@ the private local handoff and finish the real browser claim, then reconcile the
|
|
|
480
480
|
|
|
481
481
|
```sh
|
|
482
482
|
node packages/sdk-typescript/scripts/verify-setup-live.mjs \
|
|
483
|
-
--archive .artifacts/typescript/hue-run-sdk-0.13.
|
|
483
|
+
--archive .artifacts/typescript/hue-run-sdk-0.13.2.tgz \
|
|
484
484
|
--origin https://STAGING_ORIGIN \
|
|
485
485
|
--project "$project" --command claim \
|
|
486
486
|
--evidence .context/setup-staging-after-claim.json
|
|
@@ -523,10 +523,10 @@ production agent lacks. Pin the SDK and bring its `zod` peer along, so the agent
|
|
|
523
523
|
gains no dependency:
|
|
524
524
|
|
|
525
525
|
```sh
|
|
526
|
-
npx --yes --package @hue-run/sdk@0.13.
|
|
527
|
-
npx --yes --package @hue-run/sdk@0.13.
|
|
528
|
-
npx --yes --package @hue-run/sdk@0.13.
|
|
529
|
-
npx --yes --package @hue-run/sdk@0.13.
|
|
526
|
+
npx --yes --package @hue-run/sdk@0.13.2 --package "zod@^4.6.5" hue eval --case "Refund an eligible charge" --command "node agent.js" --env-file .env.hue
|
|
527
|
+
npx --yes --package @hue-run/sdk@0.13.2 --package "zod@^4.6.5" hue eval --case https://app.hue.run/projects/demo/scenarios/<id> --command "python agent.py" --timeout 120 --baseline <experiment id>
|
|
528
|
+
npx --yes --package @hue-run/sdk@0.13.2 --package "zod@^4.6.5" hue eval --set "Billing regressions" --scorer-version <id> --command "node agent.js" --save-version
|
|
529
|
+
npx --yes --package @hue-run/sdk@0.13.2 --package "zod@^4.6.5" hue eval --worker --command "node agent.js" --agent-key support-agent --revision <new-agent-revision> --env-file .env.hue
|
|
530
530
|
```
|
|
531
531
|
|
|
532
532
|
Without the second `--package`, `hue eval` exits with `hue eval needs zod`, even for `--help`;
|
|
@@ -562,7 +562,7 @@ export default function runMyAgent(inputs: JsonValue, context: SimulationTargetC
|
|
|
562
562
|
```
|
|
563
563
|
|
|
564
564
|
```sh
|
|
565
|
-
npx --yes --package @hue-run/sdk@0.13.
|
|
565
|
+
npx --yes --package @hue-run/sdk@0.13.2 --package "zod@^4.6.5" hue eval --case "Refund an eligible charge" ./hue-agent.ts --content --env-file .env.hue
|
|
566
566
|
```
|
|
567
567
|
|
|
568
568
|
`--scenario` remains an alias for `--case` for existing scripts. Pass one selection flag.
|
|
@@ -581,9 +581,11 @@ Failing cases print the scorer explanation. An evaluator Hue records as not appl
|
|
|
581
581
|
that case's columns and neither passes nor fails it, so in a mixed eval set a case is decided by
|
|
582
582
|
the evaluators that apply to it; the pass line counts the not-applicable results. A case that no
|
|
583
583
|
pinned evaluator applies to is an error that names what they need. A result of a pinned Hue judge
|
|
584
|
-
(an evaluator of kind `world_judge`) that Hue marks advisory
|
|
584
|
+
(an evaluator of kind `world_judge`) that Hue marks advisory is
|
|
585
585
|
shown in its column, marked `(advisory)`, but never decides a case or the exit code; the pass line
|
|
586
|
-
counts advisory failures as not counted, and a case only advisory results ran for is an error.
|
|
586
|
+
counts advisory failures as not counted, and a case only advisory results ran for is an error.
|
|
587
|
+
The Answer outcome evaluator uses its required judge to decide answer-only cases; if that judge
|
|
588
|
+
cannot run, the case is inconclusive. Any
|
|
587
589
|
other evaluator's result, an error, or a metric that carries `passed` is never advisory, whatever
|
|
588
590
|
its evidence says. A metric name that
|
|
589
591
|
several evaluators report, such as two judges' `verdict`, gets a column per evaluator, labelled
|
|
@@ -629,8 +631,21 @@ script name; `--revision` is sent to Hue as the agent revision of every world.
|
|
|
629
631
|
|
|
630
632
|
`--worker` registers the adapter through `runLocalAgent()` with key `--agent-key` (default: the
|
|
631
633
|
adapter filename slug), name `--agent-name` (default: the key), revision `--revision` (default:
|
|
632
|
-
`AGENT_REVISION`, then the Git `HEAD` short hash, then `dev`)
|
|
633
|
-
plus any repeated `--capability <value
|
|
634
|
+
`AGENT_REVISION`, then the Git `HEAD` short hash, then `dev`). Command workers register both
|
|
635
|
+
`environment:v1` and `direct:v1`, plus any repeated `--capability <value>`: the same worker runs
|
|
636
|
+
world cases, answer-only cases and mixed eval sets launched from Hue. Commands keep the launch
|
|
637
|
+
directory for both case kinds, so relative application entry points and configuration work.
|
|
638
|
+
Direct cases receive the task/config on stdin and private files/output through `HUE_CASE_*`,
|
|
639
|
+
without a world token, MCP connection or `HUE_ENVIRONMENT_RUN_ID`. App calls that require a world
|
|
640
|
+
must stay disabled for this handoff; never fall back to live app credentials.
|
|
641
|
+
|
|
642
|
+
Adapter-file workers register `environment:v1` by default. Add `--capability direct:v1` only when
|
|
643
|
+
the adapter also handles `context.mode === "direct"`; its direct context carries `config`, case
|
|
644
|
+
identity, `executionId`, `files`, `outputDirectory` and `signal`, with no world or tools. These
|
|
645
|
+
worker behaviors are added in TypeScript 0.13.2. Upgrading an existing command worker requires a
|
|
646
|
+
new `--revision`, because adding a capability to a previously registered revision is refused.
|
|
647
|
+
|
|
648
|
+
The worker prints the registration and each claimed run with its
|
|
634
649
|
URL, executes runs launched from Hue until Ctrl+C or `--max-runs <n>`, and prints the verdict table
|
|
635
650
|
after each run. Selection flags do not apply; Hue chooses the pinned experiment. The worker exits 0
|
|
636
651
|
when it stops normally. Hue offers a case whose world comes with agent-visible files only to a
|
package/EVALUATIONS.md
CHANGED
|
@@ -297,12 +297,19 @@ acceptance remains a post-publication Fern gate.
|
|
|
297
297
|
|
|
298
298
|
## Direct cases and files
|
|
299
299
|
|
|
300
|
-
Cases without a simulated world —
|
|
300
|
+
Cases without a simulated world — answer-only tasks, or document workflows with pinned files —
|
|
301
301
|
run on the same runner under the same checkpoint rules. They shipped in `@hue-run/sdk` `0.5.0`
|
|
302
302
|
and require a Hue deployment that serves case `inputFiles` on experiment
|
|
303
303
|
items, subject `files`, and the artifact reservation, upload, completion and download APIs. The
|
|
304
304
|
Python SDK has no equivalent.
|
|
305
305
|
|
|
306
|
+
The TypeScript 0.13.2 `hue eval --worker --command "…"` wrapper supplies both callbacks, so one
|
|
307
|
+
command worker accepts direct and world cases, including mixed eval sets. It keeps the launch
|
|
308
|
+
directory for relative application entry points; private case inputs/output still use
|
|
309
|
+
`HUE_CASE_*`. An adapter-file worker opts into the direct callback with `--capability direct:v1`
|
|
310
|
+
and must handle `context.mode === "direct"`. Restart an existing environment-only command
|
|
311
|
+
registration with a new `--revision` when upgrading.
|
|
312
|
+
|
|
306
313
|
On the outbound worker, supply `directTarget` beside or instead of `target`. Supplying
|
|
307
314
|
`directTarget` registers the `direct:v1` capability and supplying `target` registers
|
|
308
315
|
`environment:v1` (both strings are exported as `localAgentCapabilities`). Declare the file
|
package/README.md
CHANGED
|
@@ -647,10 +647,12 @@ their agents with `runLocalAgent()`; setup does not register workers or launch s
|
|
|
647
647
|
The `hue eval` command, shipped in TypeScript `0.5.0` (`--case` since `0.6.0`, `--scenario`
|
|
648
648
|
before), wraps `runSimulation()` and `runLocalAgent()` for an adapter file or a shell command:
|
|
649
649
|
`hue eval --case "<name>" ./hue-agent.ts --content` creates a fresh run from a published case's
|
|
650
|
-
immutable pins, runs the agent
|
|
650
|
+
immutable pins, runs the agent with an isolated world when the case pins one, waits
|
|
651
651
|
for Hue's outcome checks and prints the run URL and per-case PASS/FAIL verdicts with an exit code;
|
|
652
|
-
`--worker` registers the same adapter for runs launched from Hue.
|
|
653
|
-
|
|
652
|
+
`--worker` registers the same adapter for runs launched from Hue. In TypeScript 0.13.2, a
|
|
653
|
+
command worker handles both world and answer-only cases; adapter workers opt into direct cases
|
|
654
|
+
with `--capability direct:v1`. Upgrade an existing command registration under a new `--revision`.
|
|
655
|
+
It needs a Read and write key in `HUE_API_KEY` (never printed). Content capture stays off unless `--content` is
|
|
654
656
|
passed; the example passes it so case spans carry content. Case outputs, error messages and
|
|
655
657
|
explanations are stored in Hue either way (`--no-output` keeps them out of a one-shot run's
|
|
656
658
|
results); a command's stdout is its stored answer, with the credentials `hue eval` handed the case
|
package/dist/cli/eval.js
CHANGED
|
@@ -60,6 +60,8 @@ Agent (exactly one):
|
|
|
60
60
|
|
|
61
61
|
Modes:
|
|
62
62
|
--worker Register the agent and poll for runs launched from Hue
|
|
63
|
+
Commands support cases with or without a world; adapter files
|
|
64
|
+
opt into direct cases with --capability direct:v1
|
|
63
65
|
--max-runs <n> Stop the worker after n completed runs
|
|
64
66
|
--agent-key <key> Agent key (default: slug of the adapter filename)
|
|
65
67
|
--agent-name <name> Agent display name (default: the key)
|
|
@@ -600,9 +602,11 @@ function redacting(adapter) {
|
|
|
600
602
|
function parentEnvironment(allowHueCredentials) {
|
|
601
603
|
// A world variable left in this process's environment belongs to another world: only the
|
|
602
604
|
// current case's world sets them, whether or not the case has one.
|
|
603
|
-
|
|
605
|
+
const parent = withoutWorldVariables(allowHueCredentials
|
|
604
606
|
? Object.fromEntries(Object.entries(process.env).filter((entry) => entry[1] !== undefined))
|
|
605
607
|
: stripHueControlPlaneCredentials(process.env));
|
|
608
|
+
delete parent.HUE_ENVIRONMENT_RUN_ID;
|
|
609
|
+
return parent;
|
|
606
610
|
}
|
|
607
611
|
function commandAdapter(command, timeoutSeconds, options) {
|
|
608
612
|
return async (inputs, context) => {
|
|
@@ -683,7 +687,7 @@ function directCommandAdapter(command, timeoutSeconds, options) {
|
|
|
683
687
|
files: context.files,
|
|
684
688
|
});
|
|
685
689
|
const stdout = await spawnAgentCommand(command, {
|
|
686
|
-
cwd: layout.caseDirectory,
|
|
690
|
+
cwd: options.workingDirectory ?? layout.caseDirectory,
|
|
687
691
|
env: {
|
|
688
692
|
...parentEnvironment(options.allowHueCredentials),
|
|
689
693
|
HUE_CASE_DIR: layout.caseDirectory,
|
|
@@ -1286,7 +1290,7 @@ async function runDirect(run, connection) {
|
|
|
1286
1290
|
telemetryNotAccepted: report.telemetryNotAccepted,
|
|
1287
1291
|
}, run.baselineId, output, signal);
|
|
1288
1292
|
}
|
|
1289
|
-
async function runWorker(values, connection,
|
|
1293
|
+
async function runWorker(values, connection, agents, agent, hue, output, signal) {
|
|
1290
1294
|
const client = new ObservedClient(connection);
|
|
1291
1295
|
const environmentClient = createEnvironmentClient(connection);
|
|
1292
1296
|
const wait = integer("wait", values.wait, 300, 0, 86_400);
|
|
@@ -1305,6 +1309,9 @@ async function runWorker(values, connection, adapter, agent, hue, output, signal
|
|
|
1305
1309
|
output.log(`Claimed run ${claim.runId}: ${new URL(`/experiments/${claim.experimentId}`, connection.baseUrl).toString()}`);
|
|
1306
1310
|
};
|
|
1307
1311
|
const telemetry = telemetryReporter(output);
|
|
1312
|
+
// A command can use the same stdin contract for both case kinds. Existing adapter files
|
|
1313
|
+
// may require a world, so their direct context remains an explicit capability opt-in.
|
|
1314
|
+
const direct = values.command !== undefined || values.capability?.includes("direct:v1");
|
|
1308
1315
|
await runLocalAgent({
|
|
1309
1316
|
client,
|
|
1310
1317
|
environmentClient,
|
|
@@ -1339,7 +1346,7 @@ async function runWorker(values, connection, adapter, agent, hue, output, signal
|
|
|
1339
1346
|
},
|
|
1340
1347
|
target(inputs, tools, context) {
|
|
1341
1348
|
output.log(`[${context.item.externalKey}] agent started`);
|
|
1342
|
-
return
|
|
1349
|
+
return agents.simulation(inputs, {
|
|
1343
1350
|
config: context.config,
|
|
1344
1351
|
item: context.item,
|
|
1345
1352
|
executionId: context.executionId,
|
|
@@ -1355,6 +1362,22 @@ async function runWorker(values, connection, adapter, agent, hue, output, signal
|
|
|
1355
1362
|
signal: context.signal ?? signal,
|
|
1356
1363
|
});
|
|
1357
1364
|
},
|
|
1365
|
+
...(direct
|
|
1366
|
+
? {
|
|
1367
|
+
directTarget(inputs, context) {
|
|
1368
|
+
output.log(`[${context.item.externalKey}] agent started`);
|
|
1369
|
+
return agents.direct(inputs, {
|
|
1370
|
+
mode: "direct",
|
|
1371
|
+
config: context.config,
|
|
1372
|
+
item: context.item,
|
|
1373
|
+
executionId: context.executionId,
|
|
1374
|
+
files: context.files,
|
|
1375
|
+
outputDirectory: context.outputDirectory,
|
|
1376
|
+
signal: context.signal ?? signal,
|
|
1377
|
+
});
|
|
1378
|
+
},
|
|
1379
|
+
}
|
|
1380
|
+
: {}),
|
|
1358
1381
|
async onCompleted(report) {
|
|
1359
1382
|
output.log(`Run ${report.runId} completed: ${report.subjectIds.length} case${report.subjectIds.length === 1 ? "" : "s"}`);
|
|
1360
1383
|
telemetry.rest(report.telemetryNotAccepted);
|
|
@@ -1490,6 +1513,9 @@ export async function runEvalCommand(argv) {
|
|
|
1490
1513
|
direct: redacting(loaded ??
|
|
1491
1514
|
directCommandAdapter(values.command, timeout, {
|
|
1492
1515
|
allowHueCredentials: values["allow-hue-credentials"],
|
|
1516
|
+
// A worker's single command must resolve relative entry points the same way for
|
|
1517
|
+
// direct and world cases. One-shot direct runs keep their private-directory cwd.
|
|
1518
|
+
...(values.worker ? { workingDirectory: process.cwd() } : {}),
|
|
1493
1519
|
})),
|
|
1494
1520
|
};
|
|
1495
1521
|
hue = createHue({
|
|
@@ -1500,7 +1526,7 @@ export async function runEvalCommand(argv) {
|
|
|
1500
1526
|
timeoutMillis: CASE_TRACE_EXPORT_MILLIS,
|
|
1501
1527
|
});
|
|
1502
1528
|
return values.worker
|
|
1503
|
-
? await runWorker(values, connection, agents
|
|
1529
|
+
? await runWorker(values, connection, agents, agent, hue, output, controller.signal)
|
|
1504
1530
|
: await runOnce(values, connection, agents, agent, hue, output, controller.signal);
|
|
1505
1531
|
}
|
|
1506
1532
|
catch (error) {
|
package/dist/evals/client.d.ts
CHANGED
|
@@ -110,7 +110,7 @@ export declare class EvaluationClient {
|
|
|
110
110
|
createScorer(input: TaggedIdentity): Promise<Scorer>;
|
|
111
111
|
/** Renames a scorer or replaces its tags by name; the same values again change nothing. */
|
|
112
112
|
updateScorer(id: string, input: IdentityUpdate): Promise<Scorer>;
|
|
113
|
-
/** Lists the project's tags in
|
|
113
|
+
/** Lists the project's tags in its order: as people arranged them in Hue, then newer tags. */
|
|
114
114
|
listTags(): Promise<{
|
|
115
115
|
/** The project's tags. */
|
|
116
116
|
items: Tag[];
|
package/dist/evals/client.js
CHANGED
|
@@ -451,7 +451,7 @@ export class EvaluationClient {
|
|
|
451
451
|
updateScorer(id, input) {
|
|
452
452
|
return this.request("PATCH", `/scorers/${uuid(id)}`, withTagNames(input), undefined, undefined, true);
|
|
453
453
|
}
|
|
454
|
-
/** Lists the project's tags in
|
|
454
|
+
/** Lists the project's tags in its order: as people arranged them in Hue, then newer tags. */
|
|
455
455
|
listTags() {
|
|
456
456
|
return this.request("GET", "/tags");
|
|
457
457
|
}
|
|
@@ -142,12 +142,17 @@ const sdkScorerPublication = z.union([
|
|
|
142
142
|
}),
|
|
143
143
|
z.strictObject({
|
|
144
144
|
kind: z.literal("world_outcome"),
|
|
145
|
-
entry: z.
|
|
145
|
+
entry: z.enum([
|
|
146
|
+
"hue.outcome_assertions.v2",
|
|
147
|
+
"hue.outcome_assertions.v4",
|
|
148
|
+
"hue.outcome_assertions.v5",
|
|
149
|
+
"hue.outcome_assertions.v6",
|
|
150
|
+
]),
|
|
146
151
|
metrics: fixedMetrics(outcomeAssertionMetrics),
|
|
147
152
|
}),
|
|
148
153
|
z.strictObject({
|
|
149
154
|
kind: z.literal("world_outcome"),
|
|
150
|
-
entry: z.
|
|
155
|
+
entry: z.enum(["hue.outcome_assertions.v3", "hue.answer_outcome.v1", "hue.answer_outcome.v2"]),
|
|
151
156
|
metrics: fixedMetrics(outcomeAssertionV3Metrics),
|
|
152
157
|
config: z.strictObject({ judge: outcomeJudgeConfig }),
|
|
153
158
|
}),
|
package/dist/evals/types.d.ts
CHANGED
|
@@ -275,6 +275,25 @@ export type ScorerDefinition = {
|
|
|
275
275
|
/** The judge every case scored by this version uses. */
|
|
276
276
|
judge: OutcomeJudgeConfig;
|
|
277
277
|
};
|
|
278
|
+
} | {
|
|
279
|
+
/** A case's reviewed assertions, scored inside Hue from gateway evidence. */
|
|
280
|
+
kind: "world_outcome";
|
|
281
|
+
/** Versioned gateway-ledger assertion semantics. */
|
|
282
|
+
entry: "hue.outcome_assertions.v4" | "hue.outcome_assertions.v5" | "hue.outcome_assertions.v6";
|
|
283
|
+
/** `task_success` and the fixed assertion counts defined by the entry. */
|
|
284
|
+
metrics: MetricDefinition[];
|
|
285
|
+
} | {
|
|
286
|
+
/** An answer-only case, scored inside Hue without world evidence. */
|
|
287
|
+
kind: "world_outcome";
|
|
288
|
+
/** Versioned answer semantics; the pinned judge is required to decide the case. */
|
|
289
|
+
entry: "hue.answer_outcome.v1" | "hue.answer_outcome.v2";
|
|
290
|
+
/** The assertion and judge counts defined by the entry. */
|
|
291
|
+
metrics: MetricDefinition[];
|
|
292
|
+
/** The judge pin used to score the answer. */
|
|
293
|
+
config: {
|
|
294
|
+
/** The required judge every case scored by this version uses. */
|
|
295
|
+
judge: OutcomeJudgeConfig;
|
|
296
|
+
};
|
|
278
297
|
} | {
|
|
279
298
|
/** Scored by a person in Hue; the local runner defers it. */
|
|
280
299
|
kind: "manual";
|
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.13.
|
|
2
|
+
export declare const sdkVersion = "0.13.2";
|
package/dist/version.js
CHANGED