hivenet 0.6.0 → 0.7.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/README.md +14 -0
- package/dist/{chunk-DNR6HNJD.js → chunk-A3UY57EQ.js} +263 -25
- package/dist/{chunk-AK23JXBN.js → chunk-OEHURQBM.js} +1 -1
- package/dist/cli.js +85 -14
- package/dist/{doctor-EA2GJRUS.js → doctor-UOEWIXXV.js} +7 -2
- package/dist/index.cjs +249 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +174 -24
- package/dist/index.d.ts +174 -24
- package/dist/index.js +248 -28
- package/dist/index.js.map +1 -1
- package/dist/owner-I3AOD2FJ.js +1005 -0
- package/package.json +2 -1
- package/dist/owner-ZWROA7AU.js +0 -539
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
require_arg,
|
|
11
11
|
validateDescriptor,
|
|
12
12
|
validateFeedbackEvent
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-A3UY57EQ.js";
|
|
14
14
|
|
|
15
15
|
// src/doctor.ts
|
|
16
16
|
var import_arg = __toESM(require_arg(), 1);
|
|
@@ -21,6 +21,7 @@ async function runDoctor(argv, cliVersion) {
|
|
|
21
21
|
"--help": Boolean,
|
|
22
22
|
"--to": String,
|
|
23
23
|
"--dsn": String,
|
|
24
|
+
"--registry": String,
|
|
24
25
|
"--smoke": Boolean,
|
|
25
26
|
"--json": Boolean,
|
|
26
27
|
"-h": "--help",
|
|
@@ -49,7 +50,10 @@ async function runDoctor(argv, cliVersion) {
|
|
|
49
50
|
}
|
|
50
51
|
} else {
|
|
51
52
|
const to = args["--to"].trim();
|
|
52
|
-
|
|
53
|
+
if (args["--registry"] !== void 0 && (!args["--registry"].trim() || to.includes("."))) {
|
|
54
|
+
throw new FeedbackError("Use --registry with --to <project-slug>, not a domain.");
|
|
55
|
+
}
|
|
56
|
+
const descriptorUrl = to.includes(".") ? `https://${to}${WELL_KNOWN_PATH}` : `${registryUrl(args["--registry"] !== void 0 ? { HIVENET_REGISTRY: args["--registry"] } : process.env)}/v1/registry/${encodeURIComponent(to)}`;
|
|
53
57
|
const result = await checkDescriptor(descriptorUrl);
|
|
54
58
|
checks.push(result.check);
|
|
55
59
|
descriptor = result.descriptor;
|
|
@@ -200,6 +204,7 @@ function printDoctorHelp() {
|
|
|
200
204
|
Options
|
|
201
205
|
--to, -t <slug|domain> Registered slug, or a domain serving ${WELL_KNOWN_PATH}
|
|
202
206
|
--dsn <url> Explicit DSN: https://hv_pub_KEY@host/slug
|
|
207
|
+
--registry <origin> Check this server's registry with --to <slug>
|
|
203
208
|
--smoke Also send one disposable, clearly-labeled event
|
|
204
209
|
--json Machine-readable result
|
|
205
210
|
--help, -h This help
|
package/dist/index.cjs
CHANGED
|
@@ -33,10 +33,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
33
33
|
));
|
|
34
34
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
35
35
|
|
|
36
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.
|
|
36
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.30_typescript@5.9.3_yaml@2.9.1/node_modules/tsup/assets/cjs_shims.js
|
|
37
37
|
var getImportMetaUrl, importMetaUrl;
|
|
38
38
|
var init_cjs_shims = __esm({
|
|
39
|
-
"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.
|
|
39
|
+
"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.30_typescript@5.9.3_yaml@2.9.1/node_modules/tsup/assets/cjs_shims.js"() {
|
|
40
40
|
"use strict";
|
|
41
41
|
getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
42
42
|
importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
@@ -548,6 +548,7 @@ __export(index_exports, {
|
|
|
548
548
|
resolveThreadId: () => resolveThreadId,
|
|
549
549
|
sendFeedback: () => sendFeedback,
|
|
550
550
|
sentimentSchema: () => sentimentSchema,
|
|
551
|
+
threadSchema: () => threadSchema,
|
|
551
552
|
validateDescriptor: () => validateDescriptor,
|
|
552
553
|
validateFeedbackEvent: () => validateFeedbackEvent,
|
|
553
554
|
validateIngestResponse: () => validateIngestResponse
|
|
@@ -15270,6 +15271,157 @@ function mediaTypeForFilename(filename) {
|
|
|
15270
15271
|
const extension = /\.([^./\\]+)$/.exec(filename)?.[1]?.toLowerCase();
|
|
15271
15272
|
return extension && MEDIA_TYPES[extension] || "application/octet-stream";
|
|
15272
15273
|
}
|
|
15274
|
+
var evalCriterionIdSchema = external_exports.string().regex(
|
|
15275
|
+
/^[a-z][a-z0-9_]{0,47}$/,
|
|
15276
|
+
"Criterion ids are snake_case: a lowercase letter, then lowercase letters, digits or _ (at most 48)."
|
|
15277
|
+
);
|
|
15278
|
+
var weightSchema = external_exports.number().positive().max(100).optional();
|
|
15279
|
+
var evalJudgeCriterionSchema = external_exports.object({
|
|
15280
|
+
id: evalCriterionIdSchema,
|
|
15281
|
+
kind: external_exports.literal("judge"),
|
|
15282
|
+
description: external_exports.string().trim().min(1).max(2e3).describe("The yes/no question the judge answers about the result."),
|
|
15283
|
+
weight: weightSchema
|
|
15284
|
+
});
|
|
15285
|
+
var evalCommandCriterionSchema = external_exports.object({
|
|
15286
|
+
id: evalCriterionIdSchema,
|
|
15287
|
+
kind: external_exports.literal("command"),
|
|
15288
|
+
description: external_exports.string().trim().min(1).max(500).describe("What the check proves, for people reading results."),
|
|
15289
|
+
command: external_exports.string().trim().min(1).max(4e3),
|
|
15290
|
+
contains: external_exports.string().min(1).max(1e3).optional().describe("Stdout must contain this text."),
|
|
15291
|
+
regex: external_exports.string().min(1).max(500).optional().describe("Stdout must match this regex."),
|
|
15292
|
+
timeout_sec: external_exports.number().int().min(1).max(600).optional(),
|
|
15293
|
+
weight: weightSchema
|
|
15294
|
+
}).refine((criterion) => !(criterion.contains && criterion.regex), {
|
|
15295
|
+
message: "A command criterion takes contains or regex, not both."
|
|
15296
|
+
});
|
|
15297
|
+
var evalCriterionSchema = external_exports.discriminatedUnion("kind", [
|
|
15298
|
+
evalJudgeCriterionSchema,
|
|
15299
|
+
evalCommandCriterionSchema
|
|
15300
|
+
]);
|
|
15301
|
+
var evalJudgeSchema = external_exports.object({
|
|
15302
|
+
model: external_exports.string().trim().min(1).max(128).default("anthropic/claude-sonnet-5"),
|
|
15303
|
+
/** Give the judge the agent's ATIF trajectory, e.g. to grade which tool or skill it used. */
|
|
15304
|
+
reads_trajectory: external_exports.boolean().default(false),
|
|
15305
|
+
/** Workspace files the judge reads, relative to the workdir. */
|
|
15306
|
+
files: external_exports.array(external_exports.string().trim().min(1).max(256)).max(20).default([])
|
|
15307
|
+
});
|
|
15308
|
+
var ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,63}$/;
|
|
15309
|
+
var SINGLE_LINE = /^[^\r\n]+$/;
|
|
15310
|
+
var evalMcpServerSchema = external_exports.object({
|
|
15311
|
+
name: external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/),
|
|
15312
|
+
transport: external_exports.enum(["stdio", "sse", "streamable-http"]),
|
|
15313
|
+
url: external_exports.url().max(2e3).optional(),
|
|
15314
|
+
command: external_exports.string().trim().min(1).max(500).optional(),
|
|
15315
|
+
args: external_exports.array(external_exports.string().max(500)).max(30).default([])
|
|
15316
|
+
});
|
|
15317
|
+
var evalEnvironmentSchema = external_exports.object({
|
|
15318
|
+
/** The base image, e.g. `node:22-slim`. */
|
|
15319
|
+
image: external_exports.string().trim().regex(/^[A-Za-z0-9][A-Za-z0-9._\-/:@]{0,255}$/, "image must be a Docker image reference."),
|
|
15320
|
+
/** Dockerfile RUN lines, cached in the image: toolchains, not the product under test. */
|
|
15321
|
+
build: external_exports.array(external_exports.string().trim().regex(SINGLE_LINE).max(2e3)).max(30).default([]),
|
|
15322
|
+
/**
|
|
15323
|
+
* Runs before every trial, so each one tests the current product. Harbor runs it as the
|
|
15324
|
+
* healthcheck and retries it on failure, so it must be safe to run twice.
|
|
15325
|
+
*/
|
|
15326
|
+
setup: external_exports.object({
|
|
15327
|
+
command: external_exports.string().trim().min(1).max(8e3),
|
|
15328
|
+
timeout_sec: external_exports.number().int().min(10).max(3600).default(600)
|
|
15329
|
+
}).nullable().default(null),
|
|
15330
|
+
workdir: external_exports.string().regex(/^\/[A-Za-z0-9._\-/]{0,255}$/).default("/app"),
|
|
15331
|
+
network: external_exports.object({
|
|
15332
|
+
mode: external_exports.enum(["public", "allowlist", "no-network"]).default("public"),
|
|
15333
|
+
allowed_hosts: external_exports.array(external_exports.string().trim().min(1).max(253)).max(50).default([])
|
|
15334
|
+
}).prefault({}),
|
|
15335
|
+
/** Values reach setup and the agent; secret-like names take only `${VAR}` templates. */
|
|
15336
|
+
env: external_exports.record(external_exports.string().regex(ENV_NAME), external_exports.string().max(2e3)).default({}),
|
|
15337
|
+
mcp_servers: external_exports.array(evalMcpServerSchema).max(10).default([])
|
|
15338
|
+
});
|
|
15339
|
+
var evalAgentSchema = external_exports.object({
|
|
15340
|
+
timeout_sec: external_exports.number().int().min(30).max(7200).default(900)
|
|
15341
|
+
});
|
|
15342
|
+
var evalVersionFieldsSchema = external_exports.object({
|
|
15343
|
+
/** The task in the owner's words. Never the reporter's `actual` or `mistake`. */
|
|
15344
|
+
instruction: external_exports.string().trim().min(1).max(2e4),
|
|
15345
|
+
/** What "done" means, in one or two sentences. */
|
|
15346
|
+
end_goal: external_exports.string().trim().min(1).max(2e3).optional(),
|
|
15347
|
+
criteria: external_exports.array(evalCriterionSchema).min(1).max(30),
|
|
15348
|
+
judge: evalJudgeSchema.optional(),
|
|
15349
|
+
environment: evalEnvironmentSchema,
|
|
15350
|
+
agent: evalAgentSchema.prefault({}),
|
|
15351
|
+
/** A reference solution for Harbor's `oracle` agent, as a bash script. */
|
|
15352
|
+
solution: external_exports.string().trim().min(1).max(2e4).optional(),
|
|
15353
|
+
change_note: external_exports.string().trim().min(1).max(500).optional()
|
|
15354
|
+
});
|
|
15355
|
+
var evalVersionInputSchema = evalVersionFieldsSchema.refine(
|
|
15356
|
+
(input) => new Set(input.criteria.map((c) => c.id)).size === input.criteria.length,
|
|
15357
|
+
{ message: "Criterion ids must be unique.", path: ["criteria"] }
|
|
15358
|
+
);
|
|
15359
|
+
var HARBOR_ID = external_exports.string().regex(/^[0-9a-f-]{36}$/i, "Harbor ids are UUIDs.");
|
|
15360
|
+
var boundedRecord = (max) => external_exports.record(external_exports.string().min(1).max(200), external_exports.number()).refine((record2) => Object.keys(record2).length <= max, `At most ${max} keys.`);
|
|
15361
|
+
var evalTrialScenarioSchema = external_exports.object({
|
|
15362
|
+
/** Folders the job mounted (`harbor run --mounts`), by name: the path stays on the machine. */
|
|
15363
|
+
mounts: external_exports.array(external_exports.string().min(1).max(200)).max(5).optional(),
|
|
15364
|
+
/** `--skill` */
|
|
15365
|
+
skills: external_exports.array(external_exports.string().min(1).max(200)).max(20).optional(),
|
|
15366
|
+
/** `--mcp-config` */
|
|
15367
|
+
mcp_servers: external_exports.array(external_exports.string().min(1).max(100)).max(20).optional(),
|
|
15368
|
+
/** `--extra-instruction` text, or the file `--extra-instruction-path` named. */
|
|
15369
|
+
instructions: external_exports.array(external_exports.string().min(1).max(500)).max(5).optional(),
|
|
15370
|
+
/** `--ak` and `--ae`, without secret-looking names. */
|
|
15371
|
+
agent_options: external_exports.record(external_exports.string().min(1).max(64), external_exports.string().max(200)).refine((record2) => Object.keys(record2).length <= 20, "At most 20 agent options.").optional()
|
|
15372
|
+
});
|
|
15373
|
+
var evalTrialCiSchema = external_exports.object({
|
|
15374
|
+
provider: external_exports.literal("github"),
|
|
15375
|
+
/** `owner/name` */
|
|
15376
|
+
repository: external_exports.string().min(1).max(200),
|
|
15377
|
+
/** The commit under test: a pull request's head, else the commit that triggered the run. */
|
|
15378
|
+
commit: external_exports.string().regex(/^[0-9a-f]{7,64}$/i).optional(),
|
|
15379
|
+
branch: external_exports.string().min(1).max(250).optional(),
|
|
15380
|
+
pull_request: external_exports.number().int().positive().optional(),
|
|
15381
|
+
/** What started the workflow: pull_request, push, schedule, workflow_dispatch… */
|
|
15382
|
+
event: external_exports.string().min(1).max(50).optional(),
|
|
15383
|
+
run_url: external_exports.url({ protocol: /^https?$/ }).max(500).optional()
|
|
15384
|
+
});
|
|
15385
|
+
var evalTrialUploadSchema = external_exports.object({
|
|
15386
|
+
harbor_trial_id: HARBOR_ID,
|
|
15387
|
+
harbor_job_id: HARBOR_ID,
|
|
15388
|
+
harbor_job_name: external_exports.string().max(200).optional(),
|
|
15389
|
+
/** Set on a regrade: the trial it derives from. */
|
|
15390
|
+
source_harbor_trial_id: HARBOR_ID.optional(),
|
|
15391
|
+
/** `[task].name` from the trial's result: `<project slug>/<eval id>` for Hivenet tasks. */
|
|
15392
|
+
task_name: external_exports.string().min(1).max(300),
|
|
15393
|
+
/** `task.digest` from the trial's lock.json. */
|
|
15394
|
+
task_digest: external_exports.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
15395
|
+
agent: external_exports.string().min(1).max(100),
|
|
15396
|
+
agent_version: external_exports.string().max(100).optional(),
|
|
15397
|
+
model: external_exports.string().max(200).optional(),
|
|
15398
|
+
/** The reasoning effort it ran at (`harbor run --ak reasoning_effort=…`): part of the lane. */
|
|
15399
|
+
effort: external_exports.string().min(1).max(40).optional(),
|
|
15400
|
+
harbor_version: external_exports.string().max(50).optional(),
|
|
15401
|
+
exception: external_exports.object({ type: external_exports.string().min(1).max(200), message: external_exports.string().max(2e3) }).optional(),
|
|
15402
|
+
/** reward.json. Absent when the verifier wrote nothing: the trial wasn't graded. */
|
|
15403
|
+
rewards: boundedRecord(32).optional(),
|
|
15404
|
+
/** reward-details.json leaves, keyed by criterion id. */
|
|
15405
|
+
criteria: boundedRecord(64).optional(),
|
|
15406
|
+
metrics: external_exports.object({
|
|
15407
|
+
input_tokens: external_exports.number().int().nonnegative(),
|
|
15408
|
+
output_tokens: external_exports.number().int().nonnegative(),
|
|
15409
|
+
cache_tokens: external_exports.number().int().nonnegative(),
|
|
15410
|
+
cost_usd: external_exports.number().nonnegative(),
|
|
15411
|
+
setup_sec: external_exports.number().nonnegative(),
|
|
15412
|
+
agent_sec: external_exports.number().nonnegative(),
|
|
15413
|
+
verifier_sec: external_exports.number().nonnegative()
|
|
15414
|
+
}).partial().optional(),
|
|
15415
|
+
started_at: external_exports.iso.datetime({ offset: true }).optional(),
|
|
15416
|
+
finished_at: external_exports.iso.datetime({ offset: true }).optional(),
|
|
15417
|
+
scenario: evalTrialScenarioSchema.optional(),
|
|
15418
|
+
ci: evalTrialCiSchema.optional()
|
|
15419
|
+
});
|
|
15420
|
+
var MAX_TRIALS_PER_PUSH = 200;
|
|
15421
|
+
var MAX_TRAJECTORY_BYTES = 8 * 1024 * 1024;
|
|
15422
|
+
var evalResultsUploadSchema = external_exports.object({
|
|
15423
|
+
trials: external_exports.array(evalTrialUploadSchema).min(1).max(MAX_TRIALS_PER_PUSH)
|
|
15424
|
+
});
|
|
15273
15425
|
var PROTOCOL_VERSION = 1;
|
|
15274
15426
|
var MAX_FEEDBACK_LENGTH = 5e3;
|
|
15275
15427
|
var MAX_SUBJECT_LENGTH = 500;
|
|
@@ -15372,8 +15524,12 @@ var metadataSchema = external_exports.record(
|
|
|
15372
15524
|
external_exports.string().min(1).max(40),
|
|
15373
15525
|
external_exports.union([external_exports.string().max(200), external_exports.number().finite(), external_exports.boolean()])
|
|
15374
15526
|
).refine((value) => Object.keys(value).length <= 20, { message: "at most 20 metadata keys" });
|
|
15527
|
+
var threadSchema = external_exports.object({ id: external_exports.string().regex(THREAD_ID_PATTERN) });
|
|
15528
|
+
function newThreadId() {
|
|
15529
|
+
return crypto.randomUUID().replaceAll("-", "");
|
|
15530
|
+
}
|
|
15375
15531
|
var feedbackEventSchema = external_exports.object({
|
|
15376
|
-
v: external_exports.literal(PROTOCOL_VERSION),
|
|
15532
|
+
v: external_exports.literal(PROTOCOL_VERSION).default(PROTOCOL_VERSION),
|
|
15377
15533
|
/** Tenant slug or domain this feedback is addressed to. Optional when the write key implies it. */
|
|
15378
15534
|
to: external_exports.string().max(253).optional(),
|
|
15379
15535
|
feedback: external_exports.string().min(1).max(MAX_FEEDBACK_LENGTH),
|
|
@@ -15381,7 +15537,7 @@ var feedbackEventSchema = external_exports.object({
|
|
|
15381
15537
|
subject: external_exports.string().min(1).max(MAX_SUBJECT_LENGTH).optional(),
|
|
15382
15538
|
sentiment: sentimentSchema.optional(),
|
|
15383
15539
|
author: authorSchema.optional(),
|
|
15384
|
-
thread:
|
|
15540
|
+
thread: threadSchema.optional().transform((thread) => thread ?? { id: newThreadId() }),
|
|
15385
15541
|
eval: evalReportSchema.optional(),
|
|
15386
15542
|
/** Id of an owner/system question this submission answers (from a prior response's `ask`). */
|
|
15387
15543
|
question: external_exports.string().max(64).optional(),
|
|
@@ -15394,8 +15550,8 @@ var feedbackEventSchema = external_exports.object({
|
|
|
15394
15550
|
client: external_exports.object({
|
|
15395
15551
|
name: external_exports.string().max(64),
|
|
15396
15552
|
version: external_exports.string().max(32)
|
|
15397
|
-
}),
|
|
15398
|
-
consent: external_exports.object({ telemetry: external_exports.boolean() })
|
|
15553
|
+
}).default({ name: "http", version: "0" }),
|
|
15554
|
+
consent: external_exports.object({ telemetry: external_exports.boolean() }).default({ telemetry: false })
|
|
15399
15555
|
});
|
|
15400
15556
|
var knownIssueSchema = external_exports.object({
|
|
15401
15557
|
title: external_exports.string().max(120),
|
|
@@ -15487,7 +15643,7 @@ function validateIngestResponse(input) {
|
|
|
15487
15643
|
return result.success ? { ok: true, data: result.data } : { ok: false, errors: formatIssues(result.error) };
|
|
15488
15644
|
}
|
|
15489
15645
|
function feedbackEventJsonSchema() {
|
|
15490
|
-
return external_exports.toJSONSchema(feedbackEventSchema);
|
|
15646
|
+
return external_exports.toJSONSchema(feedbackEventSchema, { io: "input" });
|
|
15491
15647
|
}
|
|
15492
15648
|
function descriptorJsonSchema() {
|
|
15493
15649
|
return external_exports.toJSONSchema(descriptorSchema);
|
|
@@ -16130,7 +16286,7 @@ function inferAuthor(context) {
|
|
|
16130
16286
|
}
|
|
16131
16287
|
var CONFIG_FILE_NAME = "feedback.config.json";
|
|
16132
16288
|
var DESCRIPTOR_CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
16133
|
-
var RESOLVE_TIMEOUT_MS =
|
|
16289
|
+
var RESOLVE_TIMEOUT_MS = 1e4;
|
|
16134
16290
|
function parseDsn(dsn) {
|
|
16135
16291
|
let url2;
|
|
16136
16292
|
try {
|
|
@@ -16246,7 +16402,17 @@ function destinationFromDescriptor(descriptor, to) {
|
|
|
16246
16402
|
};
|
|
16247
16403
|
}
|
|
16248
16404
|
function registryUrl(env = process.env) {
|
|
16249
|
-
|
|
16405
|
+
const value = env[REGISTRY_ENV_VAR]?.trim() || DEFAULT_REGISTRY_URL;
|
|
16406
|
+
try {
|
|
16407
|
+
const url2 = new URL(value);
|
|
16408
|
+
if (!["http:", "https:"].includes(url2.protocol) || url2.username || url2.password || url2.search || url2.hash || url2.pathname !== "/" || !/^[a-z0-9._:[\]-]+$/i.test(url2.hostname))
|
|
16409
|
+
throw new Error("Not an origin");
|
|
16410
|
+
return url2.origin;
|
|
16411
|
+
} catch {
|
|
16412
|
+
throw new FeedbackError(
|
|
16413
|
+
"Registry must be an HTTP(S) origin, such as https://feedback.example.com, without credentials, a path, query or fragment."
|
|
16414
|
+
);
|
|
16415
|
+
}
|
|
16250
16416
|
}
|
|
16251
16417
|
async function resolveDestination(options = {}) {
|
|
16252
16418
|
const env = options.env ?? process.env;
|
|
@@ -16255,6 +16421,19 @@ async function resolveDestination(options = {}) {
|
|
|
16255
16421
|
if (options.dsn) {
|
|
16256
16422
|
return parseDsn(options.dsn);
|
|
16257
16423
|
}
|
|
16424
|
+
if (options.registry !== void 0) {
|
|
16425
|
+
const to2 = options.to?.trim();
|
|
16426
|
+
if (!options.registry.trim() || !to2 || to2.includes(".")) {
|
|
16427
|
+
throw new FeedbackError("Use --registry with --to <project-slug>, not a domain.");
|
|
16428
|
+
}
|
|
16429
|
+
const origin = registryUrl({ [REGISTRY_ENV_VAR]: options.registry });
|
|
16430
|
+
return resolveViaDescriptor(
|
|
16431
|
+
`${origin}/v1/registry/${encodeURIComponent(to2)}`,
|
|
16432
|
+
to2,
|
|
16433
|
+
fetchImpl,
|
|
16434
|
+
cacheDir
|
|
16435
|
+
);
|
|
16436
|
+
}
|
|
16258
16437
|
const envDsn = env[DSN_ENV_VAR]?.trim();
|
|
16259
16438
|
if (envDsn) {
|
|
16260
16439
|
return parseDsn(envDsn);
|
|
@@ -16317,23 +16496,24 @@ async function postEvent(options) {
|
|
|
16317
16496
|
body = void 0;
|
|
16318
16497
|
}
|
|
16319
16498
|
const parsed = validateIngestResponse(body);
|
|
16320
|
-
return {
|
|
16321
|
-
kind: "accepted",
|
|
16322
|
-
response: parsed.ok ? parsed.data : { id: "unknown", thread: options.event.thread.id }
|
|
16323
|
-
};
|
|
16499
|
+
return parsed.ok ? { kind: "accepted", response: parsed.data } : { kind: "unreachable", error: "Server returned an invalid delivery receipt." };
|
|
16324
16500
|
}
|
|
16325
16501
|
var OUTBOX_FILE = "outbox.jsonl";
|
|
16326
|
-
var
|
|
16502
|
+
var MAX_FLUSH_ENTRIES = 100;
|
|
16327
16503
|
var STALE_CLAIM_MS = 30 * 60 * 1e3;
|
|
16328
16504
|
function outboxPath(env = process.env) {
|
|
16329
16505
|
return import_path6.default.join(feedbackHomeDir(env), OUTBOX_FILE);
|
|
16330
16506
|
}
|
|
16331
16507
|
function appendToOutbox(entry, env = process.env) {
|
|
16508
|
+
return appendEntriesToOutbox([entry], env);
|
|
16509
|
+
}
|
|
16510
|
+
function appendEntriesToOutbox(entries, env) {
|
|
16511
|
+
if (entries.length === 0) return true;
|
|
16332
16512
|
try {
|
|
16333
16513
|
const file2 = outboxPath(env);
|
|
16334
16514
|
(0, import_fs3.mkdirSync)(import_path6.default.dirname(file2), { recursive: true });
|
|
16335
|
-
(0, import_fs3.appendFileSync)(file2, `${JSON.stringify(entry)}
|
|
16336
|
-
`);
|
|
16515
|
+
(0, import_fs3.appendFileSync)(file2, entries.map((entry) => `${JSON.stringify(entry)}
|
|
16516
|
+
`).join(""));
|
|
16337
16517
|
return true;
|
|
16338
16518
|
} catch {
|
|
16339
16519
|
return false;
|
|
@@ -16375,24 +16555,30 @@ function claimQueue(env) {
|
|
|
16375
16555
|
async function flushOutbox(options = {}) {
|
|
16376
16556
|
const env = options.env ?? process.env;
|
|
16377
16557
|
const claims = claimQueue(env);
|
|
16378
|
-
const entries = claims.flatMap(readEntries)
|
|
16558
|
+
const entries = claims.flatMap(readEntries);
|
|
16559
|
+
const deadline = Date.now() + (options.maxDurationMs ?? Number.POSITIVE_INFINITY);
|
|
16379
16560
|
const failures = [];
|
|
16561
|
+
let attempted = 0;
|
|
16380
16562
|
let delivered = 0;
|
|
16381
|
-
for (const entry of entries) {
|
|
16563
|
+
for (const entry of entries.slice(0, MAX_FLUSH_ENTRIES)) {
|
|
16564
|
+
const timeLeft = deadline - Date.now();
|
|
16565
|
+
if (timeLeft <= 0) break;
|
|
16566
|
+
attempted++;
|
|
16382
16567
|
const result = await postEvent({
|
|
16383
16568
|
endpoint: entry.endpoint,
|
|
16384
16569
|
...entry.writeKey ? { writeKey: entry.writeKey } : {},
|
|
16385
16570
|
event: entry.event,
|
|
16386
|
-
timeoutMs: options.timeoutMs ?? 5e3,
|
|
16571
|
+
timeoutMs: Math.max(1, Math.floor(Math.min(options.timeoutMs ?? 5e3, timeLeft))),
|
|
16387
16572
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
16388
16573
|
});
|
|
16389
|
-
if (result.kind === "accepted"
|
|
16390
|
-
delivered
|
|
16574
|
+
if (result.kind === "accepted") {
|
|
16575
|
+
delivered++;
|
|
16391
16576
|
} else {
|
|
16392
16577
|
failures.push(entry);
|
|
16393
16578
|
}
|
|
16394
16579
|
}
|
|
16395
|
-
|
|
16580
|
+
const remaining = entries.slice(attempted).concat(failures);
|
|
16581
|
+
if (appendEntriesToOutbox(remaining, env)) {
|
|
16396
16582
|
for (const claim of claims) {
|
|
16397
16583
|
try {
|
|
16398
16584
|
(0, import_fs3.rmSync)(claim, { force: true });
|
|
@@ -16400,16 +16586,22 @@ async function flushOutbox(options = {}) {
|
|
|
16400
16586
|
}
|
|
16401
16587
|
}
|
|
16402
16588
|
}
|
|
16403
|
-
return { delivered, remaining:
|
|
16589
|
+
return { delivered, remaining: remaining.length };
|
|
16404
16590
|
}
|
|
16405
16591
|
async function resolveApiOrigin(options) {
|
|
16406
|
-
|
|
16407
|
-
|
|
16592
|
+
const env = options.env ?? process.env;
|
|
16593
|
+
if (options.registry !== void 0 && !options.to && !options.dsn) {
|
|
16594
|
+
if (!options.registry.trim()) throw new FeedbackError("Registry must not be empty.");
|
|
16595
|
+
return registryUrl({ [REGISTRY_ENV_VAR]: options.registry });
|
|
16596
|
+
}
|
|
16597
|
+
if (!options.to && !options.dsn && !env[DSN_ENV_VAR]?.trim()) {
|
|
16598
|
+
return registryUrl(env);
|
|
16408
16599
|
}
|
|
16409
16600
|
const destination = await resolveDestination({
|
|
16410
16601
|
...options.to !== void 0 ? { to: options.to } : {},
|
|
16411
16602
|
...options.dsn !== void 0 ? { dsn: options.dsn } : {},
|
|
16412
|
-
...options.
|
|
16603
|
+
...options.registry !== void 0 ? { registry: options.registry } : {},
|
|
16604
|
+
env,
|
|
16413
16605
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
16414
16606
|
});
|
|
16415
16607
|
return new URL(destination.endpoint).origin;
|
|
@@ -16418,12 +16610,12 @@ function ownerApi(options) {
|
|
|
16418
16610
|
const origin = (options.apiOrigin ?? new URL(DEFAULT_REGISTRY_URL).origin).replace(/\/$/, "");
|
|
16419
16611
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
16420
16612
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
16421
|
-
async function request(path6, init) {
|
|
16613
|
+
async function request(path6, init, timeout = timeoutMs) {
|
|
16422
16614
|
let response;
|
|
16423
16615
|
try {
|
|
16424
16616
|
response = await fetchImpl(`${origin}${path6}`, {
|
|
16425
16617
|
...init,
|
|
16426
|
-
signal: AbortSignal.timeout(
|
|
16618
|
+
signal: AbortSignal.timeout(timeout),
|
|
16427
16619
|
headers: {
|
|
16428
16620
|
authorization: `Bearer ${options.secretKey}`,
|
|
16429
16621
|
...init?.body ? { "content-type": "application/json" } : {},
|
|
@@ -16556,6 +16748,33 @@ function ownerApi(options) {
|
|
|
16556
16748
|
body: JSON.stringify({ status, ...note !== void 0 ? { note } : {} })
|
|
16557
16749
|
});
|
|
16558
16750
|
},
|
|
16751
|
+
/** Draft a runnable version of an eval (a person approves it in the dashboard). */
|
|
16752
|
+
async draftEvalVersion(id, fields) {
|
|
16753
|
+
return request(`/v1/evals/${encodeURIComponent(id)}/versions`, {
|
|
16754
|
+
method: "POST",
|
|
16755
|
+
body: JSON.stringify(fields)
|
|
16756
|
+
});
|
|
16757
|
+
},
|
|
16758
|
+
/** Compiled Harbor tasks: every accepted eval's current version, or the given refs. */
|
|
16759
|
+
async pullEvalTasks(refs = []) {
|
|
16760
|
+
const query = refs.map((ref) => `ref=${encodeURIComponent(ref)}`).join("&");
|
|
16761
|
+
return request(`/v1/evals/tasks${query ? `?${query}` : ""}`);
|
|
16762
|
+
},
|
|
16763
|
+
/** Harbor trials read from a job directory, with their grades. */
|
|
16764
|
+
async pushEvalResults(trials) {
|
|
16765
|
+
return request("/v1/evals/results", {
|
|
16766
|
+
method: "POST",
|
|
16767
|
+
body: JSON.stringify({ trials })
|
|
16768
|
+
});
|
|
16769
|
+
},
|
|
16770
|
+
/** A stored trial's ATIF trajectory (`agent/trajectory.json`), as read from disk. */
|
|
16771
|
+
async pushTrialTrajectory(harborTrialId, trajectory) {
|
|
16772
|
+
return request(
|
|
16773
|
+
`/v1/evals/trials/${encodeURIComponent(harborTrialId)}/trajectory`,
|
|
16774
|
+
{ method: "PUT", body: trajectory },
|
|
16775
|
+
Math.max(timeoutMs, 6e4)
|
|
16776
|
+
);
|
|
16777
|
+
},
|
|
16559
16778
|
/** Attach an external link (Slack message, Linear/GitHub issue, PR) to evt_… or iss_…. */
|
|
16560
16779
|
async addLink(id, url2, label) {
|
|
16561
16780
|
const path6 = id.startsWith("iss_") ? `/v1/issues/${id}` : `/v1/events/${id}`;
|
|
@@ -16595,6 +16814,7 @@ async function prepareFeedback(options) {
|
|
|
16595
16814
|
const resolveOptions = {
|
|
16596
16815
|
...options.to !== void 0 ? { to: options.to } : {},
|
|
16597
16816
|
...options.dsn !== void 0 ? { dsn: options.dsn } : {},
|
|
16817
|
+
...options.registry !== void 0 ? { registry: options.registry } : {},
|
|
16598
16818
|
cwd,
|
|
16599
16819
|
env,
|
|
16600
16820
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
@@ -16764,6 +16984,7 @@ async function sendFeedback(options) {
|
|
|
16764
16984
|
resolveThreadId,
|
|
16765
16985
|
sendFeedback,
|
|
16766
16986
|
sentimentSchema,
|
|
16987
|
+
threadSchema,
|
|
16767
16988
|
validateDescriptor,
|
|
16768
16989
|
validateFeedbackEvent,
|
|
16769
16990
|
validateIngestResponse
|