@hue-run/sdk 0.4.1 → 0.5.0

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.
@@ -1 +1,17 @@
1
- export {};
1
+ /** A target's saved outcome when it produced files. Create it with `withFiles`. */
2
+ export class TargetResult {
3
+ output;
4
+ files;
5
+ constructor(
6
+ /** JSON output of the target, or `undefined` when it produced only files. */
7
+ output,
8
+ /** Generated files to save with the execution. */
9
+ files) {
10
+ this.output = output;
11
+ this.files = files;
12
+ }
13
+ }
14
+ /** Return this from a target to save generated files with the execution. */
15
+ export function withFiles(output, files) {
16
+ return new TargetResult(output, files);
17
+ }
@@ -0,0 +1,161 @@
1
+ import type { EvaluationClient } from "./client.js";
2
+ import type { ExperimentItem, Metric, Subject, TypedError } from "./types.js";
3
+ /** Subset of {@link EvaluationClient} used to wait for results. */
4
+ export type VerdictClient = Pick<EvaluationClient, "listEvaluationItems" | "listResults" | "getResult">;
5
+ /** Options for {@link waitForResults}. */
6
+ export interface WaitForResultsOptions {
7
+ /** Evaluation run to read, for example `report.runId` or `experiment.evaluation.id`. */
8
+ runId: string;
9
+ /** Scorer versions every item must have a terminal result for. */
10
+ scorerVersionIds: string[];
11
+ /** Restrict the wait to these subjects, for example `report.subjectIds`; defaults to every item. */
12
+ subjectIds?: string[];
13
+ /** Overall budget in milliseconds; `0` reads once. Default 300000. */
14
+ timeoutMillis?: number;
15
+ /** Delay between reads in milliseconds, 250–60000. Default 2000. */
16
+ pollIntervalMillis?: number;
17
+ /** Stops waiting early; the partial state is returned with `complete: false`. */
18
+ signal?: AbortSignal;
19
+ }
20
+ /** One stored result joined to its evaluation item. */
21
+ export interface VerdictResult {
22
+ /** Result ID. */
23
+ id: string;
24
+ /** Evaluation item the result scores. */
25
+ itemId: string;
26
+ /** Immutable subject behind the item. */
27
+ subjectId: string;
28
+ /** Scorer version that produced it. */
29
+ scorerVersionId: string;
30
+ /** Terminal outcome state. */
31
+ state: "scored" | "error" | "skipped";
32
+ /** Reported metrics; empty unless scored. */
33
+ metrics: Metric[];
34
+ /** Scorer explanation, or `null` when absent or not persisted. */
35
+ explanation: string | null;
36
+ /** Scorer failure for `state: "error"`, otherwise `null`. */
37
+ error: TypedError | null;
38
+ }
39
+ /** Outcome of {@link waitForResults}. */
40
+ export interface VerdictResults {
41
+ /** Whether every item has a terminal result for every pinned scorer version. */
42
+ complete: boolean;
43
+ /** Evaluation items that were waited for. */
44
+ items: {
45
+ /** Evaluation item ID. */
46
+ id: string;
47
+ /** Immutable subject behind the item. */
48
+ subjectId: string;
49
+ }[];
50
+ /** Terminal results read so far, one per item and scorer version. */
51
+ results: VerdictResult[];
52
+ }
53
+ /**
54
+ * Polls an evaluation run until every item has a terminal (`scored`, `error` or `skipped`)
55
+ * result for every pinned scorer version, or the budget elapses. Hue-executed pins such as
56
+ * `world_outcome` are graded after the world seals, so a caller that wants verdicts waits here
57
+ * after the runner returns. A timeout or abort returns the partial state with `complete: false`.
58
+ */
59
+ export declare function waitForResults(client: VerdictClient, options: WaitForResultsOptions): Promise<VerdictResults>;
60
+ /** Per-case verdict derived from every pinned scorer's result. */
61
+ export interface CaseVerdict {
62
+ /** Frozen experiment-case identity. */
63
+ caseId: string;
64
+ /** Caller-chosen case key. */
65
+ externalKey: string;
66
+ /** Subject scored for the case, or `null` before completion. */
67
+ subjectId: string | null;
68
+ /** `passed` and `failed` are scored verdicts; `error`, `skipped` and `pending` carry no verdict. */
69
+ state: "passed" | "failed" | "error" | "skipped" | "pending";
70
+ /** True only for `state: "passed"`: every scored metric passed and no pin errored or is missing. */
71
+ passed: boolean;
72
+ /** Reported metrics across pinned scorers, in result order. */
73
+ metrics: (Metric & {
74
+ /** Scorer version that reported the metric. */
75
+ scorerVersionId: string;
76
+ })[];
77
+ /** Explanations of results that did not pass, when persisted. */
78
+ explanations: string[];
79
+ /** Error types of errored results. */
80
+ errors: string[];
81
+ }
82
+ /** Per-case rows and totals for one evaluation run. */
83
+ export interface VerdictSummary {
84
+ /** One row per experiment case, in experiment order. */
85
+ cases: CaseVerdict[];
86
+ /** Case counts by verdict state. */
87
+ totals: {
88
+ /** All cases. */
89
+ cases: number;
90
+ /** Cases whose every metric passed. */
91
+ passed: number;
92
+ /** Cases with a failing metric. */
93
+ failed: number;
94
+ /** Cases with a scorer error. */
95
+ error: number;
96
+ /** Cases whose pins were all skipped. */
97
+ skipped: number;
98
+ /** Cases still missing a result. */
99
+ pending: number;
100
+ };
101
+ }
102
+ /** Whether one reported metric counts as passing: an explicit `passed`, else a true boolean. */
103
+ export declare function metricPassed(metric: Metric): boolean;
104
+ /**
105
+ * Groups results by experiment case. Cases link to results through their execution's subject;
106
+ * pass `subjects` when the items do not carry `execution.subjectId`. A case passes when every
107
+ * pinned scorer scored it without a failing metric.
108
+ */
109
+ export declare function summarizeVerdicts(results: VerdictResults, options: {
110
+ /** Experiment items, in the order rows should appear. */
111
+ experimentItems: Pick<ExperimentItem, "id" | "externalKey" | "execution">[];
112
+ /** Scorer versions every case needs a result for; defaults to the versions seen in `results`. */
113
+ scorerVersionIds?: string[];
114
+ /** Subject to case links for servers that omit `execution.subjectId`. */
115
+ subjects?: Pick<Subject, "id" | "caseId">[];
116
+ }): VerdictSummary;
117
+ /** Per-case change between a baseline and the current run, keyed by case key. */
118
+ export interface VerdictComparison {
119
+ /** Cases that pass now but did not in the baseline. */
120
+ improvements: number;
121
+ /** Cases that passed in the baseline but do not now. */
122
+ regressions: number;
123
+ /** Cases with the same verdict, including cases present in only one run. */
124
+ unchanged: number;
125
+ /** Every case key seen in either run. */
126
+ cases: {
127
+ /** Caller-chosen case key. */
128
+ externalKey: string;
129
+ /** Baseline state, or `missing`. */
130
+ before: CaseVerdict["state"] | "missing";
131
+ /** Current state, or `missing`. */
132
+ after: CaseVerdict["state"] | "missing";
133
+ /** Direction of the change. */
134
+ change: "improved" | "regressed" | "unchanged";
135
+ }[];
136
+ }
137
+ /** Diffs the current summary against a baseline by case key. */
138
+ export declare function compareVerdicts(current: VerdictSummary, baseline: VerdictSummary): VerdictComparison;
139
+ /** Options for {@link collectExperimentVerdicts}. */
140
+ export interface CollectExperimentVerdictsOptions extends Omit<WaitForResultsOptions, "runId" | "scorerVersionIds"> {
141
+ /** Experiment whose evaluation run is read. */
142
+ experimentId: string;
143
+ }
144
+ /** Verdicts of one experiment: its run identity, the raw results and the per-case summary. */
145
+ export interface ExperimentVerdicts {
146
+ /** Experiment ID. */
147
+ experimentId: string;
148
+ /** The experiment's evaluation run. */
149
+ runId: string;
150
+ /** Scorer versions pinned by the experiment. */
151
+ scorerVersionIds: string[];
152
+ /** Raw results and completeness. */
153
+ results: VerdictResults;
154
+ /** Per-case rows and totals. */
155
+ summary: VerdictSummary;
156
+ }
157
+ /**
158
+ * Reads an experiment's pinned scorer versions, waits for its results and summarizes them per
159
+ * case. Subject links fall back to reading each subject when the items omit them.
160
+ */
161
+ export declare function collectExperimentVerdicts(client: VerdictClient & Pick<EvaluationClient, "getExperiment" | "listExperimentItems" | "getSubject">, options: CollectExperimentVerdictsOptions): Promise<ExperimentVerdicts>;
@@ -0,0 +1,192 @@
1
+ import { uuid } from "./json.js";
2
+ const TERMINAL = new Set(["scored", "error", "skipped"]);
3
+ async function allPages(page) {
4
+ const items = [];
5
+ const cursors = new Set();
6
+ let after;
7
+ do {
8
+ const response = await page(after);
9
+ items.push(...response.items);
10
+ if (items.length > 5000)
11
+ throw new RangeError("Runs of more than 5000 items are unsupported");
12
+ if (response.nextCursor === null)
13
+ break;
14
+ after = uuid(response.nextCursor);
15
+ if (cursors.has(after))
16
+ throw new Error("API pagination repeated a cursor");
17
+ cursors.add(after);
18
+ } while (after !== undefined);
19
+ return items;
20
+ }
21
+ function sleep(milliseconds, signal) {
22
+ return new Promise((resolve) => {
23
+ const timer = setTimeout(done, milliseconds);
24
+ function done() {
25
+ signal?.removeEventListener("abort", done);
26
+ clearTimeout(timer);
27
+ resolve();
28
+ }
29
+ signal?.addEventListener("abort", done, { once: true });
30
+ });
31
+ }
32
+ /**
33
+ * Polls an evaluation run until every item has a terminal (`scored`, `error` or `skipped`)
34
+ * result for every pinned scorer version, or the budget elapses. Hue-executed pins such as
35
+ * `world_outcome` are graded after the world seals, so a caller that wants verdicts waits here
36
+ * after the runner returns. A timeout or abort returns the partial state with `complete: false`.
37
+ */
38
+ export async function waitForResults(client, options) {
39
+ const timeout = options.timeoutMillis ?? 300_000;
40
+ const interval = options.pollIntervalMillis ?? 2_000;
41
+ if (!Number.isInteger(timeout) || timeout < 0)
42
+ throw new RangeError("timeoutMillis must be ≥ 0");
43
+ if (!Number.isInteger(interval) || interval < 250 || interval > 60_000)
44
+ throw new RangeError("pollIntervalMillis must be 250–60000");
45
+ const wanted = options.subjectIds ? new Set(options.subjectIds) : undefined;
46
+ const pins = [...new Set(options.scorerVersionIds)];
47
+ const deadline = Date.now() + timeout;
48
+ for (;;) {
49
+ const listed = await allPages((after) => client.listEvaluationItems(options.runId, { after }));
50
+ const items = listed
51
+ .filter((item) => !wanted || wanted.has(item.subjectId))
52
+ .map((item) => ({ id: item.id, subjectId: item.subjectId }));
53
+ const summaries = await allPages((after) => client.listResults(options.runId, { after }));
54
+ const found = new Map();
55
+ for (const summary of summaries)
56
+ if (TERMINAL.has(summary.state))
57
+ found.set(`${summary.itemId}:${summary.scorerVersionId}`, summary.id);
58
+ const missing = items.flatMap((item) => pins.filter((pin) => !found.has(`${item.id}:${pin}`)).map((pin) => `${item.id}:${pin}`));
59
+ const complete = missing.length === 0 && (wanted === undefined || items.length === wanted.size);
60
+ if (complete || Date.now() >= deadline || options.signal?.aborted) {
61
+ const subjects = new Map(items.map((item) => [item.id, item.subjectId]));
62
+ const results = [];
63
+ for (const item of items)
64
+ for (const pin of pins) {
65
+ const id = found.get(`${item.id}:${pin}`);
66
+ if (!id)
67
+ continue;
68
+ const stored = await client.getResult(id);
69
+ results.push({
70
+ id: stored.id,
71
+ itemId: stored.itemId,
72
+ subjectId: subjects.get(stored.itemId) ?? item.subjectId,
73
+ scorerVersionId: stored.scorerVersionId,
74
+ state: stored.state,
75
+ metrics: stored.state === "scored" ? stored.metrics : [],
76
+ explanation: stored.explanation ?? null,
77
+ error: stored.error ?? null,
78
+ });
79
+ }
80
+ return { complete, items, results };
81
+ }
82
+ await sleep(Math.min(interval, Math.max(0, deadline - Date.now())), options.signal);
83
+ }
84
+ }
85
+ /** Whether one reported metric counts as passing: an explicit `passed`, else a true boolean. */
86
+ export function metricPassed(metric) {
87
+ if (metric.passed !== undefined)
88
+ return metric.passed;
89
+ return typeof metric.value === "boolean" ? metric.value : true;
90
+ }
91
+ /**
92
+ * Groups results by experiment case. Cases link to results through their execution's subject;
93
+ * pass `subjects` when the items do not carry `execution.subjectId`. A case passes when every
94
+ * pinned scorer scored it without a failing metric.
95
+ */
96
+ export function summarizeVerdicts(results, options) {
97
+ const pins = new Set(options.scorerVersionIds ?? results.results.map((result) => result.scorerVersionId));
98
+ const subjectByCase = new Map();
99
+ for (const subject of options.subjects ?? [])
100
+ subjectByCase.set(subject.caseId, subject.id);
101
+ for (const item of options.experimentItems)
102
+ if (item.execution?.subjectId)
103
+ subjectByCase.set(item.id, item.execution.subjectId);
104
+ const cases = options.experimentItems.map((item) => {
105
+ const subjectId = subjectByCase.get(item.id) ?? null;
106
+ const own = subjectId ? results.results.filter((result) => result.subjectId === subjectId) : [];
107
+ const metrics = own.flatMap((result) => result.metrics.map((metric) => ({ ...metric, scorerVersionId: result.scorerVersionId })));
108
+ const errors = own.filter((result) => result.state === "error");
109
+ const scored = own.filter((result) => result.state === "scored");
110
+ const failing = scored.filter((result) => !result.metrics.every(metricPassed));
111
+ const missing = [...pins].some((pin) => !own.some((result) => result.scorerVersionId === pin));
112
+ const state = errors.length
113
+ ? "error"
114
+ : failing.length
115
+ ? "failed"
116
+ : missing || !own.length
117
+ ? "pending"
118
+ : scored.length
119
+ ? "passed"
120
+ : "skipped";
121
+ return {
122
+ caseId: item.id,
123
+ externalKey: item.externalKey,
124
+ subjectId,
125
+ state,
126
+ passed: state === "passed",
127
+ metrics,
128
+ explanations: own
129
+ .filter((result) => result.state !== "scored" || failing.includes(result))
130
+ .map((result) => result.explanation)
131
+ .filter((explanation) => !!explanation),
132
+ errors: errors.map((result) => result.error?.type ?? "ScorerError"),
133
+ };
134
+ });
135
+ const totals = { cases: cases.length, passed: 0, failed: 0, error: 0, skipped: 0, pending: 0 };
136
+ for (const item of cases)
137
+ totals[item.state]++;
138
+ return { cases, totals };
139
+ }
140
+ /** Diffs the current summary against a baseline by case key. */
141
+ export function compareVerdicts(current, baseline) {
142
+ const before = new Map(baseline.cases.map((item) => [item.externalKey, item.state]));
143
+ const after = new Map(current.cases.map((item) => [item.externalKey, item.state]));
144
+ const keys = [...new Set([...after.keys(), ...before.keys()])];
145
+ const comparison = {
146
+ improvements: 0,
147
+ regressions: 0,
148
+ unchanged: 0,
149
+ cases: [],
150
+ };
151
+ for (const externalKey of keys) {
152
+ const previous = before.get(externalKey) ?? "missing";
153
+ const next = after.get(externalKey) ?? "missing";
154
+ const change = previous !== "missing" && next !== "missing" && previous !== "passed" && next === "passed"
155
+ ? "improved"
156
+ : previous === "passed" && next !== "passed" && next !== "missing"
157
+ ? "regressed"
158
+ : "unchanged";
159
+ comparison[change === "improved" ? "improvements" : change === "regressed" ? "regressions" : "unchanged"]++;
160
+ comparison.cases.push({ externalKey, before: previous, after: next, change });
161
+ }
162
+ return comparison;
163
+ }
164
+ /**
165
+ * Reads an experiment's pinned scorer versions, waits for its results and summarizes them per
166
+ * case. Subject links fall back to reading each subject when the items omit them.
167
+ */
168
+ export async function collectExperimentVerdicts(client, options) {
169
+ const experiment = await client.getExperiment(options.experimentId);
170
+ const scorerVersionIds = experiment.evaluation.scorerVersions.map((version) => version.id);
171
+ const { experimentId: _experimentId, ...wait } = options;
172
+ const results = await waitForResults(client, {
173
+ ...wait,
174
+ runId: experiment.evaluation.id,
175
+ scorerVersionIds,
176
+ });
177
+ const experimentItems = await allPages((after) => client.listExperimentItems(experiment.id, { after }));
178
+ const linked = new Set(experimentItems.map((item) => item.execution?.subjectId).filter((id) => !!id));
179
+ const subjects = [];
180
+ for (const item of results.items)
181
+ if (!linked.has(item.subjectId)) {
182
+ const subject = await client.getSubject(item.subjectId);
183
+ subjects.push({ id: subject.id, caseId: subject.caseId });
184
+ }
185
+ return {
186
+ experimentId: experiment.id,
187
+ runId: experiment.evaluation.id,
188
+ scorerVersionIds,
189
+ results,
190
+ summary: summarizeVerdicts(results, { experimentItems, scorerVersionIds, subjects }),
191
+ };
192
+ }
package/dist/evals.d.ts CHANGED
@@ -1,13 +1,19 @@
1
1
  export { createEvaluationClient, EvaluationClient, HueApiError } from "./evals/client.js";
2
2
  export type { EvaluationClientOptions } from "./evals/client.js";
3
3
  export { runExperiment, rescore, UncertainExecutionError, OutcomeSerializationError, TargetCancelledError, TargetOutcomeUncertainError, } from "./evals/runner.js";
4
- export type { RunExperimentOptions, RescoreOptions, RunnerReport } from "./evals/runner.js";
4
+ export type { RunExperimentOptions, RunExperimentTargetContext, RescoreOptions, RunnerReport, } from "./evals/runner.js";
5
+ export { TargetResult, withFiles } from "./evals/types.js";
6
+ export { outputContentTypes, outputFileLimits, OutputFileError, safeFilename, targetFileRoles, } from "./evals/files.js";
5
7
  export { runSimulation } from "./evals/simulation.js";
6
- export type { RepositorySimulationCase, RepositorySimulationScorer, RunSimulationOptions, SimulationProgress, SimulationReport, SimulationScenario, SimulationTargetContext, } from "./evals/simulation.js";
8
+ export type { RepositorySimulationCase, RepositorySimulationScorer, RunSimulationOptions, SimulationDefinition, SimulationProgress, SimulationReport, SimulationScenario, SimulationTargetContext, } from "./evals/simulation.js";
7
9
  export { actualAgentManifestV2, agentManifestDigestV2, attemptBaselineV2, attemptBindingRead, attemptConnectionBundleV2, attemptIdentityV2, dependencyManifestV2, dependencyProviderV2, expectedAgentManifestV2, executionManifestDigestV2, parityEvidenceV2, preflightFindingV2, preflightReportV2, prepareAttemptInputV2, projectMcpConnectionV2, secretFreeBindingV2, surfaceBindingV2, } from "./evals/attempt.js";
8
10
  export type { ActualAgentManifestInputV2, ActualAgentManifestV2, AttemptBaselineV2, AttemptBindingRead, AttemptConnectionBundleV2, AttemptIdentityV2, DependencyManifestV2, DependencyProviderV2, ExpectedAgentManifestV2, ParityEvidenceV2, PreflightFindingV2, PreflightReportV2, PrepareAttemptIncompleteV2, PrepareAttemptInputV2, PrepareAttemptReadyV2, PrepareAttemptRequestV2, PrepareAttemptResultV2, RefreshAttemptResultV2, RequestedAttemptProviderV2, RevokeAttemptResult, SurfaceBindingV2, } from "./evals/attempt.js";
9
11
  export { builtins, defineLocalScorer, scoreLocally } from "./evals/scorers.js";
10
12
  export { sourceDigest } from "./evals/json.js";
11
13
  export type * from "./evals/types.js";
12
- export { runLocalAgent } from "./evals/local-worker.js";
13
- export type { LocalAgentTargetContext, RunLocalAgentOptions } from "./evals/local-worker.js";
14
+ export { localAgentCapabilities, registeredCapabilities, runLocalAgent, } from "./evals/local-worker.js";
15
+ export type { LocalAgentDirectContext, LocalAgentTargetContext, RunLocalAgentOptions, } from "./evals/local-worker.js";
16
+ export { getScenario, listScenarios, matchByName, parseScenarioSelector, resolveEvalSetPins, resolveScenarioPins, } from "./evals/scenarios.js";
17
+ export type { NamedCandidate, NameMatch, ScenarioClient, ScenarioPins, ScenarioSelector, } from "./evals/scenarios.js";
18
+ export { collectExperimentVerdicts, compareVerdicts, metricPassed, summarizeVerdicts, waitForResults, } from "./evals/verdicts.js";
19
+ export type { CaseVerdict, CollectExperimentVerdictsOptions, ExperimentVerdicts, VerdictClient, VerdictComparison, VerdictResult, VerdictResults, VerdictSummary, WaitForResultsOptions, } from "./evals/verdicts.js";
package/dist/evals.js CHANGED
@@ -1,7 +1,11 @@
1
1
  export { createEvaluationClient, EvaluationClient, HueApiError } from "./evals/client.js";
2
2
  export { runExperiment, rescore, UncertainExecutionError, OutcomeSerializationError, TargetCancelledError, TargetOutcomeUncertainError, } from "./evals/runner.js";
3
+ export { TargetResult, withFiles } from "./evals/types.js";
4
+ export { outputContentTypes, outputFileLimits, OutputFileError, safeFilename, targetFileRoles, } from "./evals/files.js";
3
5
  export { runSimulation } from "./evals/simulation.js";
4
6
  export { actualAgentManifestV2, agentManifestDigestV2, attemptBaselineV2, attemptBindingRead, attemptConnectionBundleV2, attemptIdentityV2, dependencyManifestV2, dependencyProviderV2, expectedAgentManifestV2, executionManifestDigestV2, parityEvidenceV2, preflightFindingV2, preflightReportV2, prepareAttemptInputV2, projectMcpConnectionV2, secretFreeBindingV2, surfaceBindingV2, } from "./evals/attempt.js";
5
7
  export { builtins, defineLocalScorer, scoreLocally } from "./evals/scorers.js";
6
8
  export { sourceDigest } from "./evals/json.js";
7
- export { runLocalAgent } from "./evals/local-worker.js";
9
+ export { localAgentCapabilities, registeredCapabilities, runLocalAgent, } from "./evals/local-worker.js";
10
+ export { getScenario, listScenarios, matchByName, parseScenarioSelector, resolveEvalSetPins, resolveScenarioPins, } from "./evals/scenarios.js";
11
+ export { collectExperimentVerdicts, compareVerdicts, metricPassed, summarizeVerdicts, waitForResults, } from "./evals/verdicts.js";
package/dist/setup/cli.js CHANGED
@@ -8,6 +8,13 @@ import { renderHumanEvent, renderJsonlEvent, renderPlainEvent, selectSetupOutput
8
8
  import { runSetup } from "./runner.js";
9
9
  import { SETUP_EVENT_CONTRACT_VERSION } from "./types.js";
10
10
  const commands = new Set(["setup", "resume", "status", "claim"]);
11
+ // Additional commands live in ../cli and load lazily so the setup parser, its usage text and its
12
+ // JSONL error contract stay untouched for every other input. Add a command with one entry.
13
+ const extensions = new Map([
14
+ ["eval", async () => (await import("../cli/eval.js")).runEvalCommand(process.argv.slice(3))],
15
+ ["login", async () => (await import("../cli/login.js")).runLoginCommand(process.argv.slice(3))],
16
+ ["mcp", async () => (await import("../cli/mcp.js")).runMcpCommand(process.argv.slice(3))],
17
+ ]);
11
18
  function writeEvent(event, mode, width) {
12
19
  const line = mode === "jsonl"
13
20
  ? renderJsonlEvent(event)
@@ -18,6 +25,9 @@ function writeEvent(event, mode, width) {
18
25
  process.stdout.write(`${line}\n`);
19
26
  }
20
27
  async function main() {
28
+ const extension = extensions.get(process.argv[2] ?? "");
29
+ if (extension)
30
+ return extension();
21
31
  const agentRequested = process.argv.slice(2).includes("--agent");
22
32
  let parsed;
23
33
  try {
@@ -37,7 +47,7 @@ async function main() {
37
47
  }
38
48
  catch {
39
49
  if (!agentRequested) {
40
- process.stderr.write("Usage: hue <setup|resume|status|claim> [--agent|--format human|plain|jsonl] [--project PATH] [--origin URL] [--restart]\n");
50
+ process.stderr.write("Usage: hue <setup|resume|status|claim|login|eval|mcp> [--agent|--format human|plain|jsonl] [--project PATH] [--origin URL] [--restart]\n");
41
51
  return 2;
42
52
  }
43
53
  const event = {
@@ -68,7 +78,7 @@ async function main() {
68
78
  process.stdout.write(`${renderJsonlEvent(event)}\n`);
69
79
  return 2;
70
80
  }
71
- process.stdout.write("Usage: hue <setup|resume|status|claim> [--agent|--format human|plain|jsonl] [--project PATH] [--origin URL] [--restart]\n");
81
+ process.stdout.write("Usage: hue <setup|resume|status|claim|login|eval|mcp> [--agent|--format human|plain|jsonl] [--project PATH] [--origin URL] [--restart]\n");
72
82
  return 0;
73
83
  }
74
84
  const command = parsed.positionals[0];
@@ -100,7 +110,7 @@ async function main() {
100
110
  process.stdout.write(`${renderJsonlEvent(event)}\n`);
101
111
  }
102
112
  else
103
- process.stderr.write("Usage: hue <setup|resume|status|claim> [--agent|--format human|plain|jsonl] [--project PATH] [--origin URL] [--restart]\n");
113
+ process.stderr.write("Usage: hue <setup|resume|status|claim|login|eval|mcp> [--agent|--format human|plain|jsonl] [--project PATH] [--origin URL] [--restart]\n");
104
114
  return 2;
105
115
  }
106
116
  const mode = selectSetupOutputMode({
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.4.1";
2
+ export declare const sdkVersion = "0.5.0";
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.4.1";
3
+ export const sdkVersion = "0.5.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hue-run/sdk",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "publishConfig": {