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
package/dist/index.js
CHANGED
|
@@ -31,11 +31,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
mod
|
|
32
32
|
));
|
|
33
33
|
|
|
34
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.
|
|
34
|
+
// ../../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/esm_shims.js
|
|
35
35
|
import path from "path";
|
|
36
36
|
import { fileURLToPath } from "url";
|
|
37
37
|
var init_esm_shims = __esm({
|
|
38
|
-
"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.
|
|
38
|
+
"../../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/esm_shims.js"() {
|
|
39
39
|
"use strict";
|
|
40
40
|
}
|
|
41
41
|
});
|
|
@@ -15209,6 +15209,157 @@ function mediaTypeForFilename(filename) {
|
|
|
15209
15209
|
const extension = /\.([^./\\]+)$/.exec(filename)?.[1]?.toLowerCase();
|
|
15210
15210
|
return extension && MEDIA_TYPES[extension] || "application/octet-stream";
|
|
15211
15211
|
}
|
|
15212
|
+
var evalCriterionIdSchema = external_exports.string().regex(
|
|
15213
|
+
/^[a-z][a-z0-9_]{0,47}$/,
|
|
15214
|
+
"Criterion ids are snake_case: a lowercase letter, then lowercase letters, digits or _ (at most 48)."
|
|
15215
|
+
);
|
|
15216
|
+
var weightSchema = external_exports.number().positive().max(100).optional();
|
|
15217
|
+
var evalJudgeCriterionSchema = external_exports.object({
|
|
15218
|
+
id: evalCriterionIdSchema,
|
|
15219
|
+
kind: external_exports.literal("judge"),
|
|
15220
|
+
description: external_exports.string().trim().min(1).max(2e3).describe("The yes/no question the judge answers about the result."),
|
|
15221
|
+
weight: weightSchema
|
|
15222
|
+
});
|
|
15223
|
+
var evalCommandCriterionSchema = external_exports.object({
|
|
15224
|
+
id: evalCriterionIdSchema,
|
|
15225
|
+
kind: external_exports.literal("command"),
|
|
15226
|
+
description: external_exports.string().trim().min(1).max(500).describe("What the check proves, for people reading results."),
|
|
15227
|
+
command: external_exports.string().trim().min(1).max(4e3),
|
|
15228
|
+
contains: external_exports.string().min(1).max(1e3).optional().describe("Stdout must contain this text."),
|
|
15229
|
+
regex: external_exports.string().min(1).max(500).optional().describe("Stdout must match this regex."),
|
|
15230
|
+
timeout_sec: external_exports.number().int().min(1).max(600).optional(),
|
|
15231
|
+
weight: weightSchema
|
|
15232
|
+
}).refine((criterion) => !(criterion.contains && criterion.regex), {
|
|
15233
|
+
message: "A command criterion takes contains or regex, not both."
|
|
15234
|
+
});
|
|
15235
|
+
var evalCriterionSchema = external_exports.discriminatedUnion("kind", [
|
|
15236
|
+
evalJudgeCriterionSchema,
|
|
15237
|
+
evalCommandCriterionSchema
|
|
15238
|
+
]);
|
|
15239
|
+
var evalJudgeSchema = external_exports.object({
|
|
15240
|
+
model: external_exports.string().trim().min(1).max(128).default("anthropic/claude-sonnet-5"),
|
|
15241
|
+
/** Give the judge the agent's ATIF trajectory, e.g. to grade which tool or skill it used. */
|
|
15242
|
+
reads_trajectory: external_exports.boolean().default(false),
|
|
15243
|
+
/** Workspace files the judge reads, relative to the workdir. */
|
|
15244
|
+
files: external_exports.array(external_exports.string().trim().min(1).max(256)).max(20).default([])
|
|
15245
|
+
});
|
|
15246
|
+
var ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,63}$/;
|
|
15247
|
+
var SINGLE_LINE = /^[^\r\n]+$/;
|
|
15248
|
+
var evalMcpServerSchema = external_exports.object({
|
|
15249
|
+
name: external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/),
|
|
15250
|
+
transport: external_exports.enum(["stdio", "sse", "streamable-http"]),
|
|
15251
|
+
url: external_exports.url().max(2e3).optional(),
|
|
15252
|
+
command: external_exports.string().trim().min(1).max(500).optional(),
|
|
15253
|
+
args: external_exports.array(external_exports.string().max(500)).max(30).default([])
|
|
15254
|
+
});
|
|
15255
|
+
var evalEnvironmentSchema = external_exports.object({
|
|
15256
|
+
/** The base image, e.g. `node:22-slim`. */
|
|
15257
|
+
image: external_exports.string().trim().regex(/^[A-Za-z0-9][A-Za-z0-9._\-/:@]{0,255}$/, "image must be a Docker image reference."),
|
|
15258
|
+
/** Dockerfile RUN lines, cached in the image: toolchains, not the product under test. */
|
|
15259
|
+
build: external_exports.array(external_exports.string().trim().regex(SINGLE_LINE).max(2e3)).max(30).default([]),
|
|
15260
|
+
/**
|
|
15261
|
+
* Runs before every trial, so each one tests the current product. Harbor runs it as the
|
|
15262
|
+
* healthcheck and retries it on failure, so it must be safe to run twice.
|
|
15263
|
+
*/
|
|
15264
|
+
setup: external_exports.object({
|
|
15265
|
+
command: external_exports.string().trim().min(1).max(8e3),
|
|
15266
|
+
timeout_sec: external_exports.number().int().min(10).max(3600).default(600)
|
|
15267
|
+
}).nullable().default(null),
|
|
15268
|
+
workdir: external_exports.string().regex(/^\/[A-Za-z0-9._\-/]{0,255}$/).default("/app"),
|
|
15269
|
+
network: external_exports.object({
|
|
15270
|
+
mode: external_exports.enum(["public", "allowlist", "no-network"]).default("public"),
|
|
15271
|
+
allowed_hosts: external_exports.array(external_exports.string().trim().min(1).max(253)).max(50).default([])
|
|
15272
|
+
}).prefault({}),
|
|
15273
|
+
/** Values reach setup and the agent; secret-like names take only `${VAR}` templates. */
|
|
15274
|
+
env: external_exports.record(external_exports.string().regex(ENV_NAME), external_exports.string().max(2e3)).default({}),
|
|
15275
|
+
mcp_servers: external_exports.array(evalMcpServerSchema).max(10).default([])
|
|
15276
|
+
});
|
|
15277
|
+
var evalAgentSchema = external_exports.object({
|
|
15278
|
+
timeout_sec: external_exports.number().int().min(30).max(7200).default(900)
|
|
15279
|
+
});
|
|
15280
|
+
var evalVersionFieldsSchema = external_exports.object({
|
|
15281
|
+
/** The task in the owner's words. Never the reporter's `actual` or `mistake`. */
|
|
15282
|
+
instruction: external_exports.string().trim().min(1).max(2e4),
|
|
15283
|
+
/** What "done" means, in one or two sentences. */
|
|
15284
|
+
end_goal: external_exports.string().trim().min(1).max(2e3).optional(),
|
|
15285
|
+
criteria: external_exports.array(evalCriterionSchema).min(1).max(30),
|
|
15286
|
+
judge: evalJudgeSchema.optional(),
|
|
15287
|
+
environment: evalEnvironmentSchema,
|
|
15288
|
+
agent: evalAgentSchema.prefault({}),
|
|
15289
|
+
/** A reference solution for Harbor's `oracle` agent, as a bash script. */
|
|
15290
|
+
solution: external_exports.string().trim().min(1).max(2e4).optional(),
|
|
15291
|
+
change_note: external_exports.string().trim().min(1).max(500).optional()
|
|
15292
|
+
});
|
|
15293
|
+
var evalVersionInputSchema = evalVersionFieldsSchema.refine(
|
|
15294
|
+
(input) => new Set(input.criteria.map((c) => c.id)).size === input.criteria.length,
|
|
15295
|
+
{ message: "Criterion ids must be unique.", path: ["criteria"] }
|
|
15296
|
+
);
|
|
15297
|
+
var HARBOR_ID = external_exports.string().regex(/^[0-9a-f-]{36}$/i, "Harbor ids are UUIDs.");
|
|
15298
|
+
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.`);
|
|
15299
|
+
var evalTrialScenarioSchema = external_exports.object({
|
|
15300
|
+
/** Folders the job mounted (`harbor run --mounts`), by name: the path stays on the machine. */
|
|
15301
|
+
mounts: external_exports.array(external_exports.string().min(1).max(200)).max(5).optional(),
|
|
15302
|
+
/** `--skill` */
|
|
15303
|
+
skills: external_exports.array(external_exports.string().min(1).max(200)).max(20).optional(),
|
|
15304
|
+
/** `--mcp-config` */
|
|
15305
|
+
mcp_servers: external_exports.array(external_exports.string().min(1).max(100)).max(20).optional(),
|
|
15306
|
+
/** `--extra-instruction` text, or the file `--extra-instruction-path` named. */
|
|
15307
|
+
instructions: external_exports.array(external_exports.string().min(1).max(500)).max(5).optional(),
|
|
15308
|
+
/** `--ak` and `--ae`, without secret-looking names. */
|
|
15309
|
+
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()
|
|
15310
|
+
});
|
|
15311
|
+
var evalTrialCiSchema = external_exports.object({
|
|
15312
|
+
provider: external_exports.literal("github"),
|
|
15313
|
+
/** `owner/name` */
|
|
15314
|
+
repository: external_exports.string().min(1).max(200),
|
|
15315
|
+
/** The commit under test: a pull request's head, else the commit that triggered the run. */
|
|
15316
|
+
commit: external_exports.string().regex(/^[0-9a-f]{7,64}$/i).optional(),
|
|
15317
|
+
branch: external_exports.string().min(1).max(250).optional(),
|
|
15318
|
+
pull_request: external_exports.number().int().positive().optional(),
|
|
15319
|
+
/** What started the workflow: pull_request, push, schedule, workflow_dispatch… */
|
|
15320
|
+
event: external_exports.string().min(1).max(50).optional(),
|
|
15321
|
+
run_url: external_exports.url({ protocol: /^https?$/ }).max(500).optional()
|
|
15322
|
+
});
|
|
15323
|
+
var evalTrialUploadSchema = external_exports.object({
|
|
15324
|
+
harbor_trial_id: HARBOR_ID,
|
|
15325
|
+
harbor_job_id: HARBOR_ID,
|
|
15326
|
+
harbor_job_name: external_exports.string().max(200).optional(),
|
|
15327
|
+
/** Set on a regrade: the trial it derives from. */
|
|
15328
|
+
source_harbor_trial_id: HARBOR_ID.optional(),
|
|
15329
|
+
/** `[task].name` from the trial's result: `<project slug>/<eval id>` for Hivenet tasks. */
|
|
15330
|
+
task_name: external_exports.string().min(1).max(300),
|
|
15331
|
+
/** `task.digest` from the trial's lock.json. */
|
|
15332
|
+
task_digest: external_exports.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
15333
|
+
agent: external_exports.string().min(1).max(100),
|
|
15334
|
+
agent_version: external_exports.string().max(100).optional(),
|
|
15335
|
+
model: external_exports.string().max(200).optional(),
|
|
15336
|
+
/** The reasoning effort it ran at (`harbor run --ak reasoning_effort=…`): part of the lane. */
|
|
15337
|
+
effort: external_exports.string().min(1).max(40).optional(),
|
|
15338
|
+
harbor_version: external_exports.string().max(50).optional(),
|
|
15339
|
+
exception: external_exports.object({ type: external_exports.string().min(1).max(200), message: external_exports.string().max(2e3) }).optional(),
|
|
15340
|
+
/** reward.json. Absent when the verifier wrote nothing: the trial wasn't graded. */
|
|
15341
|
+
rewards: boundedRecord(32).optional(),
|
|
15342
|
+
/** reward-details.json leaves, keyed by criterion id. */
|
|
15343
|
+
criteria: boundedRecord(64).optional(),
|
|
15344
|
+
metrics: external_exports.object({
|
|
15345
|
+
input_tokens: external_exports.number().int().nonnegative(),
|
|
15346
|
+
output_tokens: external_exports.number().int().nonnegative(),
|
|
15347
|
+
cache_tokens: external_exports.number().int().nonnegative(),
|
|
15348
|
+
cost_usd: external_exports.number().nonnegative(),
|
|
15349
|
+
setup_sec: external_exports.number().nonnegative(),
|
|
15350
|
+
agent_sec: external_exports.number().nonnegative(),
|
|
15351
|
+
verifier_sec: external_exports.number().nonnegative()
|
|
15352
|
+
}).partial().optional(),
|
|
15353
|
+
started_at: external_exports.iso.datetime({ offset: true }).optional(),
|
|
15354
|
+
finished_at: external_exports.iso.datetime({ offset: true }).optional(),
|
|
15355
|
+
scenario: evalTrialScenarioSchema.optional(),
|
|
15356
|
+
ci: evalTrialCiSchema.optional()
|
|
15357
|
+
});
|
|
15358
|
+
var MAX_TRIALS_PER_PUSH = 200;
|
|
15359
|
+
var MAX_TRAJECTORY_BYTES = 8 * 1024 * 1024;
|
|
15360
|
+
var evalResultsUploadSchema = external_exports.object({
|
|
15361
|
+
trials: external_exports.array(evalTrialUploadSchema).min(1).max(MAX_TRIALS_PER_PUSH)
|
|
15362
|
+
});
|
|
15212
15363
|
var PROTOCOL_VERSION = 1;
|
|
15213
15364
|
var MAX_FEEDBACK_LENGTH = 5e3;
|
|
15214
15365
|
var MAX_SUBJECT_LENGTH = 500;
|
|
@@ -15311,8 +15462,12 @@ var metadataSchema = external_exports.record(
|
|
|
15311
15462
|
external_exports.string().min(1).max(40),
|
|
15312
15463
|
external_exports.union([external_exports.string().max(200), external_exports.number().finite(), external_exports.boolean()])
|
|
15313
15464
|
).refine((value) => Object.keys(value).length <= 20, { message: "at most 20 metadata keys" });
|
|
15465
|
+
var threadSchema = external_exports.object({ id: external_exports.string().regex(THREAD_ID_PATTERN) });
|
|
15466
|
+
function newThreadId() {
|
|
15467
|
+
return crypto.randomUUID().replaceAll("-", "");
|
|
15468
|
+
}
|
|
15314
15469
|
var feedbackEventSchema = external_exports.object({
|
|
15315
|
-
v: external_exports.literal(PROTOCOL_VERSION),
|
|
15470
|
+
v: external_exports.literal(PROTOCOL_VERSION).default(PROTOCOL_VERSION),
|
|
15316
15471
|
/** Tenant slug or domain this feedback is addressed to. Optional when the write key implies it. */
|
|
15317
15472
|
to: external_exports.string().max(253).optional(),
|
|
15318
15473
|
feedback: external_exports.string().min(1).max(MAX_FEEDBACK_LENGTH),
|
|
@@ -15320,7 +15475,7 @@ var feedbackEventSchema = external_exports.object({
|
|
|
15320
15475
|
subject: external_exports.string().min(1).max(MAX_SUBJECT_LENGTH).optional(),
|
|
15321
15476
|
sentiment: sentimentSchema.optional(),
|
|
15322
15477
|
author: authorSchema.optional(),
|
|
15323
|
-
thread:
|
|
15478
|
+
thread: threadSchema.optional().transform((thread) => thread ?? { id: newThreadId() }),
|
|
15324
15479
|
eval: evalReportSchema.optional(),
|
|
15325
15480
|
/** Id of an owner/system question this submission answers (from a prior response's `ask`). */
|
|
15326
15481
|
question: external_exports.string().max(64).optional(),
|
|
@@ -15333,8 +15488,8 @@ var feedbackEventSchema = external_exports.object({
|
|
|
15333
15488
|
client: external_exports.object({
|
|
15334
15489
|
name: external_exports.string().max(64),
|
|
15335
15490
|
version: external_exports.string().max(32)
|
|
15336
|
-
}),
|
|
15337
|
-
consent: external_exports.object({ telemetry: external_exports.boolean() })
|
|
15491
|
+
}).default({ name: "http", version: "0" }),
|
|
15492
|
+
consent: external_exports.object({ telemetry: external_exports.boolean() }).default({ telemetry: false })
|
|
15338
15493
|
});
|
|
15339
15494
|
var knownIssueSchema = external_exports.object({
|
|
15340
15495
|
title: external_exports.string().max(120),
|
|
@@ -15426,7 +15581,7 @@ function validateIngestResponse(input) {
|
|
|
15426
15581
|
return result.success ? { ok: true, data: result.data } : { ok: false, errors: formatIssues(result.error) };
|
|
15427
15582
|
}
|
|
15428
15583
|
function feedbackEventJsonSchema() {
|
|
15429
|
-
return external_exports.toJSONSchema(feedbackEventSchema);
|
|
15584
|
+
return external_exports.toJSONSchema(feedbackEventSchema, { io: "input" });
|
|
15430
15585
|
}
|
|
15431
15586
|
function descriptorJsonSchema() {
|
|
15432
15587
|
return external_exports.toJSONSchema(descriptorSchema);
|
|
@@ -16069,7 +16224,7 @@ function inferAuthor(context) {
|
|
|
16069
16224
|
}
|
|
16070
16225
|
var CONFIG_FILE_NAME = "feedback.config.json";
|
|
16071
16226
|
var DESCRIPTOR_CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
16072
|
-
var RESOLVE_TIMEOUT_MS =
|
|
16227
|
+
var RESOLVE_TIMEOUT_MS = 1e4;
|
|
16073
16228
|
function parseDsn(dsn) {
|
|
16074
16229
|
let url2;
|
|
16075
16230
|
try {
|
|
@@ -16185,7 +16340,17 @@ function destinationFromDescriptor(descriptor, to) {
|
|
|
16185
16340
|
};
|
|
16186
16341
|
}
|
|
16187
16342
|
function registryUrl(env = process.env) {
|
|
16188
|
-
|
|
16343
|
+
const value = env[REGISTRY_ENV_VAR]?.trim() || DEFAULT_REGISTRY_URL;
|
|
16344
|
+
try {
|
|
16345
|
+
const url2 = new URL(value);
|
|
16346
|
+
if (!["http:", "https:"].includes(url2.protocol) || url2.username || url2.password || url2.search || url2.hash || url2.pathname !== "/" || !/^[a-z0-9._:[\]-]+$/i.test(url2.hostname))
|
|
16347
|
+
throw new Error("Not an origin");
|
|
16348
|
+
return url2.origin;
|
|
16349
|
+
} catch {
|
|
16350
|
+
throw new FeedbackError(
|
|
16351
|
+
"Registry must be an HTTP(S) origin, such as https://feedback.example.com, without credentials, a path, query or fragment."
|
|
16352
|
+
);
|
|
16353
|
+
}
|
|
16189
16354
|
}
|
|
16190
16355
|
async function resolveDestination(options = {}) {
|
|
16191
16356
|
const env = options.env ?? process.env;
|
|
@@ -16194,6 +16359,19 @@ async function resolveDestination(options = {}) {
|
|
|
16194
16359
|
if (options.dsn) {
|
|
16195
16360
|
return parseDsn(options.dsn);
|
|
16196
16361
|
}
|
|
16362
|
+
if (options.registry !== void 0) {
|
|
16363
|
+
const to2 = options.to?.trim();
|
|
16364
|
+
if (!options.registry.trim() || !to2 || to2.includes(".")) {
|
|
16365
|
+
throw new FeedbackError("Use --registry with --to <project-slug>, not a domain.");
|
|
16366
|
+
}
|
|
16367
|
+
const origin = registryUrl({ [REGISTRY_ENV_VAR]: options.registry });
|
|
16368
|
+
return resolveViaDescriptor(
|
|
16369
|
+
`${origin}/v1/registry/${encodeURIComponent(to2)}`,
|
|
16370
|
+
to2,
|
|
16371
|
+
fetchImpl,
|
|
16372
|
+
cacheDir
|
|
16373
|
+
);
|
|
16374
|
+
}
|
|
16197
16375
|
const envDsn = env[DSN_ENV_VAR]?.trim();
|
|
16198
16376
|
if (envDsn) {
|
|
16199
16377
|
return parseDsn(envDsn);
|
|
@@ -16256,23 +16434,24 @@ async function postEvent(options) {
|
|
|
16256
16434
|
body = void 0;
|
|
16257
16435
|
}
|
|
16258
16436
|
const parsed = validateIngestResponse(body);
|
|
16259
|
-
return {
|
|
16260
|
-
kind: "accepted",
|
|
16261
|
-
response: parsed.ok ? parsed.data : { id: "unknown", thread: options.event.thread.id }
|
|
16262
|
-
};
|
|
16437
|
+
return parsed.ok ? { kind: "accepted", response: parsed.data } : { kind: "unreachable", error: "Server returned an invalid delivery receipt." };
|
|
16263
16438
|
}
|
|
16264
16439
|
var OUTBOX_FILE = "outbox.jsonl";
|
|
16265
|
-
var
|
|
16440
|
+
var MAX_FLUSH_ENTRIES = 100;
|
|
16266
16441
|
var STALE_CLAIM_MS = 30 * 60 * 1e3;
|
|
16267
16442
|
function outboxPath(env = process.env) {
|
|
16268
16443
|
return path5.join(feedbackHomeDir(env), OUTBOX_FILE);
|
|
16269
16444
|
}
|
|
16270
16445
|
function appendToOutbox(entry, env = process.env) {
|
|
16446
|
+
return appendEntriesToOutbox([entry], env);
|
|
16447
|
+
}
|
|
16448
|
+
function appendEntriesToOutbox(entries, env) {
|
|
16449
|
+
if (entries.length === 0) return true;
|
|
16271
16450
|
try {
|
|
16272
16451
|
const file2 = outboxPath(env);
|
|
16273
16452
|
mkdirSync2(path5.dirname(file2), { recursive: true });
|
|
16274
|
-
appendFileSync(file2, `${JSON.stringify(entry)}
|
|
16275
|
-
`);
|
|
16453
|
+
appendFileSync(file2, entries.map((entry) => `${JSON.stringify(entry)}
|
|
16454
|
+
`).join(""));
|
|
16276
16455
|
return true;
|
|
16277
16456
|
} catch {
|
|
16278
16457
|
return false;
|
|
@@ -16314,24 +16493,30 @@ function claimQueue(env) {
|
|
|
16314
16493
|
async function flushOutbox(options = {}) {
|
|
16315
16494
|
const env = options.env ?? process.env;
|
|
16316
16495
|
const claims = claimQueue(env);
|
|
16317
|
-
const entries = claims.flatMap(readEntries)
|
|
16496
|
+
const entries = claims.flatMap(readEntries);
|
|
16497
|
+
const deadline = Date.now() + (options.maxDurationMs ?? Number.POSITIVE_INFINITY);
|
|
16318
16498
|
const failures = [];
|
|
16499
|
+
let attempted = 0;
|
|
16319
16500
|
let delivered = 0;
|
|
16320
|
-
for (const entry of entries) {
|
|
16501
|
+
for (const entry of entries.slice(0, MAX_FLUSH_ENTRIES)) {
|
|
16502
|
+
const timeLeft = deadline - Date.now();
|
|
16503
|
+
if (timeLeft <= 0) break;
|
|
16504
|
+
attempted++;
|
|
16321
16505
|
const result = await postEvent({
|
|
16322
16506
|
endpoint: entry.endpoint,
|
|
16323
16507
|
...entry.writeKey ? { writeKey: entry.writeKey } : {},
|
|
16324
16508
|
event: entry.event,
|
|
16325
|
-
timeoutMs: options.timeoutMs ?? 5e3,
|
|
16509
|
+
timeoutMs: Math.max(1, Math.floor(Math.min(options.timeoutMs ?? 5e3, timeLeft))),
|
|
16326
16510
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
16327
16511
|
});
|
|
16328
|
-
if (result.kind === "accepted"
|
|
16329
|
-
delivered
|
|
16512
|
+
if (result.kind === "accepted") {
|
|
16513
|
+
delivered++;
|
|
16330
16514
|
} else {
|
|
16331
16515
|
failures.push(entry);
|
|
16332
16516
|
}
|
|
16333
16517
|
}
|
|
16334
|
-
|
|
16518
|
+
const remaining = entries.slice(attempted).concat(failures);
|
|
16519
|
+
if (appendEntriesToOutbox(remaining, env)) {
|
|
16335
16520
|
for (const claim of claims) {
|
|
16336
16521
|
try {
|
|
16337
16522
|
rmSync(claim, { force: true });
|
|
@@ -16339,16 +16524,22 @@ async function flushOutbox(options = {}) {
|
|
|
16339
16524
|
}
|
|
16340
16525
|
}
|
|
16341
16526
|
}
|
|
16342
|
-
return { delivered, remaining:
|
|
16527
|
+
return { delivered, remaining: remaining.length };
|
|
16343
16528
|
}
|
|
16344
16529
|
async function resolveApiOrigin(options) {
|
|
16345
|
-
|
|
16346
|
-
|
|
16530
|
+
const env = options.env ?? process.env;
|
|
16531
|
+
if (options.registry !== void 0 && !options.to && !options.dsn) {
|
|
16532
|
+
if (!options.registry.trim()) throw new FeedbackError("Registry must not be empty.");
|
|
16533
|
+
return registryUrl({ [REGISTRY_ENV_VAR]: options.registry });
|
|
16534
|
+
}
|
|
16535
|
+
if (!options.to && !options.dsn && !env[DSN_ENV_VAR]?.trim()) {
|
|
16536
|
+
return registryUrl(env);
|
|
16347
16537
|
}
|
|
16348
16538
|
const destination = await resolveDestination({
|
|
16349
16539
|
...options.to !== void 0 ? { to: options.to } : {},
|
|
16350
16540
|
...options.dsn !== void 0 ? { dsn: options.dsn } : {},
|
|
16351
|
-
...options.
|
|
16541
|
+
...options.registry !== void 0 ? { registry: options.registry } : {},
|
|
16542
|
+
env,
|
|
16352
16543
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
16353
16544
|
});
|
|
16354
16545
|
return new URL(destination.endpoint).origin;
|
|
@@ -16357,12 +16548,12 @@ function ownerApi(options) {
|
|
|
16357
16548
|
const origin = (options.apiOrigin ?? new URL(DEFAULT_REGISTRY_URL).origin).replace(/\/$/, "");
|
|
16358
16549
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
16359
16550
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
16360
|
-
async function request(path6, init) {
|
|
16551
|
+
async function request(path6, init, timeout = timeoutMs) {
|
|
16361
16552
|
let response;
|
|
16362
16553
|
try {
|
|
16363
16554
|
response = await fetchImpl(`${origin}${path6}`, {
|
|
16364
16555
|
...init,
|
|
16365
|
-
signal: AbortSignal.timeout(
|
|
16556
|
+
signal: AbortSignal.timeout(timeout),
|
|
16366
16557
|
headers: {
|
|
16367
16558
|
authorization: `Bearer ${options.secretKey}`,
|
|
16368
16559
|
...init?.body ? { "content-type": "application/json" } : {},
|
|
@@ -16495,6 +16686,33 @@ function ownerApi(options) {
|
|
|
16495
16686
|
body: JSON.stringify({ status, ...note !== void 0 ? { note } : {} })
|
|
16496
16687
|
});
|
|
16497
16688
|
},
|
|
16689
|
+
/** Draft a runnable version of an eval (a person approves it in the dashboard). */
|
|
16690
|
+
async draftEvalVersion(id, fields) {
|
|
16691
|
+
return request(`/v1/evals/${encodeURIComponent(id)}/versions`, {
|
|
16692
|
+
method: "POST",
|
|
16693
|
+
body: JSON.stringify(fields)
|
|
16694
|
+
});
|
|
16695
|
+
},
|
|
16696
|
+
/** Compiled Harbor tasks: every accepted eval's current version, or the given refs. */
|
|
16697
|
+
async pullEvalTasks(refs = []) {
|
|
16698
|
+
const query = refs.map((ref) => `ref=${encodeURIComponent(ref)}`).join("&");
|
|
16699
|
+
return request(`/v1/evals/tasks${query ? `?${query}` : ""}`);
|
|
16700
|
+
},
|
|
16701
|
+
/** Harbor trials read from a job directory, with their grades. */
|
|
16702
|
+
async pushEvalResults(trials) {
|
|
16703
|
+
return request("/v1/evals/results", {
|
|
16704
|
+
method: "POST",
|
|
16705
|
+
body: JSON.stringify({ trials })
|
|
16706
|
+
});
|
|
16707
|
+
},
|
|
16708
|
+
/** A stored trial's ATIF trajectory (`agent/trajectory.json`), as read from disk. */
|
|
16709
|
+
async pushTrialTrajectory(harborTrialId, trajectory) {
|
|
16710
|
+
return request(
|
|
16711
|
+
`/v1/evals/trials/${encodeURIComponent(harborTrialId)}/trajectory`,
|
|
16712
|
+
{ method: "PUT", body: trajectory },
|
|
16713
|
+
Math.max(timeoutMs, 6e4)
|
|
16714
|
+
);
|
|
16715
|
+
},
|
|
16498
16716
|
/** Attach an external link (Slack message, Linear/GitHub issue, PR) to evt_… or iss_…. */
|
|
16499
16717
|
async addLink(id, url2, label) {
|
|
16500
16718
|
const path6 = id.startsWith("iss_") ? `/v1/issues/${id}` : `/v1/events/${id}`;
|
|
@@ -16534,6 +16752,7 @@ async function prepareFeedback(options) {
|
|
|
16534
16752
|
const resolveOptions = {
|
|
16535
16753
|
...options.to !== void 0 ? { to: options.to } : {},
|
|
16536
16754
|
...options.dsn !== void 0 ? { dsn: options.dsn } : {},
|
|
16755
|
+
...options.registry !== void 0 ? { registry: options.registry } : {},
|
|
16537
16756
|
cwd,
|
|
16538
16757
|
env,
|
|
16539
16758
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
@@ -16702,6 +16921,7 @@ export {
|
|
|
16702
16921
|
resolveThreadId,
|
|
16703
16922
|
sendFeedback,
|
|
16704
16923
|
sentimentSchema,
|
|
16924
|
+
threadSchema,
|
|
16705
16925
|
validateDescriptor,
|
|
16706
16926
|
validateFeedbackEvent,
|
|
16707
16927
|
validateIngestResponse
|