hivenet 0.4.2 → 0.6.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.
- package/README.md +55 -0
- package/dist/chunk-AK23JXBN.js +32 -0
- package/dist/{chunk-WWPF6V2Y.js → chunk-DNR6HNJD.js} +484 -70
- package/dist/cli.js +323 -66
- package/dist/{doctor-CVWF7J3P.js → doctor-EA2GJRUS.js} +1 -1
- package/dist/index.cjs +868 -460
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +384 -31
- package/dist/index.d.ts +384 -31
- package/dist/index.js +863 -457
- package/dist/index.js.map +1 -1
- package/dist/owner-ZWROA7AU.js +539 -0
- package/package.json +1 -1
- package/dist/owner-N2MSYLV7.js +0 -257
|
@@ -1389,10 +1389,10 @@ function mergeDefs(...defs) {
|
|
|
1389
1389
|
function cloneDef(schema) {
|
|
1390
1390
|
return mergeDefs(schema._zod.def);
|
|
1391
1391
|
}
|
|
1392
|
-
function getElementAtPath(obj,
|
|
1393
|
-
if (!
|
|
1392
|
+
function getElementAtPath(obj, path6) {
|
|
1393
|
+
if (!path6)
|
|
1394
1394
|
return obj;
|
|
1395
|
-
return
|
|
1395
|
+
return path6.reduce((acc, key) => acc?.[key], obj);
|
|
1396
1396
|
}
|
|
1397
1397
|
function promiseAllObject(promisesObj) {
|
|
1398
1398
|
const keys = Object.keys(promisesObj);
|
|
@@ -1801,11 +1801,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1801
1801
|
}
|
|
1802
1802
|
return false;
|
|
1803
1803
|
}
|
|
1804
|
-
function prefixIssues(
|
|
1804
|
+
function prefixIssues(path6, issues) {
|
|
1805
1805
|
return issues.map((iss) => {
|
|
1806
1806
|
var _a3;
|
|
1807
1807
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
1808
|
-
iss.path.unshift(
|
|
1808
|
+
iss.path.unshift(path6);
|
|
1809
1809
|
return iss;
|
|
1810
1810
|
});
|
|
1811
1811
|
}
|
|
@@ -1952,16 +1952,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1952
1952
|
}
|
|
1953
1953
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
1954
1954
|
const fieldErrors = { _errors: [] };
|
|
1955
|
-
const processError = (error52,
|
|
1955
|
+
const processError = (error52, path6 = []) => {
|
|
1956
1956
|
for (const issue2 of error52.issues) {
|
|
1957
1957
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1958
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1958
|
+
issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
|
|
1959
1959
|
} else if (issue2.code === "invalid_key") {
|
|
1960
|
-
processError({ issues: issue2.issues }, [...
|
|
1960
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
1961
1961
|
} else if (issue2.code === "invalid_element") {
|
|
1962
|
-
processError({ issues: issue2.issues }, [...
|
|
1962
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
1963
1963
|
} else {
|
|
1964
|
-
const fullpath = [...
|
|
1964
|
+
const fullpath = [...path6, ...issue2.path];
|
|
1965
1965
|
if (fullpath.length === 0) {
|
|
1966
1966
|
fieldErrors._errors.push(mapper(issue2));
|
|
1967
1967
|
} else {
|
|
@@ -1988,17 +1988,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1988
1988
|
}
|
|
1989
1989
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
1990
1990
|
const result = { errors: [] };
|
|
1991
|
-
const processError = (error52,
|
|
1991
|
+
const processError = (error52, path6 = []) => {
|
|
1992
1992
|
var _a3, _b;
|
|
1993
1993
|
for (const issue2 of error52.issues) {
|
|
1994
1994
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1995
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1995
|
+
issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
|
|
1996
1996
|
} else if (issue2.code === "invalid_key") {
|
|
1997
|
-
processError({ issues: issue2.issues }, [...
|
|
1997
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
1998
1998
|
} else if (issue2.code === "invalid_element") {
|
|
1999
|
-
processError({ issues: issue2.issues }, [...
|
|
1999
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
2000
2000
|
} else {
|
|
2001
|
-
const fullpath = [...
|
|
2001
|
+
const fullpath = [...path6, ...issue2.path];
|
|
2002
2002
|
if (fullpath.length === 0) {
|
|
2003
2003
|
result.errors.push(mapper(issue2));
|
|
2004
2004
|
continue;
|
|
@@ -2030,8 +2030,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2030
2030
|
}
|
|
2031
2031
|
function toDotPath(_path) {
|
|
2032
2032
|
const segs = [];
|
|
2033
|
-
const
|
|
2034
|
-
for (const seg of
|
|
2033
|
+
const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
2034
|
+
for (const seg of path6) {
|
|
2035
2035
|
if (typeof seg === "number")
|
|
2036
2036
|
segs.push(`[${seg}]`);
|
|
2037
2037
|
else if (typeof seg === "symbol")
|
|
@@ -14723,13 +14723,13 @@ function resolveRef(ref, ctx) {
|
|
|
14723
14723
|
if (!ref.startsWith("#")) {
|
|
14724
14724
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
14725
14725
|
}
|
|
14726
|
-
const
|
|
14727
|
-
if (
|
|
14726
|
+
const path6 = ref.slice(1).split("/").filter(Boolean);
|
|
14727
|
+
if (path6.length === 0) {
|
|
14728
14728
|
return ctx.rootSchema;
|
|
14729
14729
|
}
|
|
14730
14730
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
14731
|
-
if (
|
|
14732
|
-
const key =
|
|
14731
|
+
if (path6[0] === defsKey) {
|
|
14732
|
+
const key = path6[1];
|
|
14733
14733
|
if (!key || !ctx.defs[key]) {
|
|
14734
14734
|
throw new Error(`Reference not found: ${ref}`);
|
|
14735
14735
|
}
|
|
@@ -15138,6 +15138,102 @@ function date4(params) {
|
|
|
15138
15138
|
config(en_default());
|
|
15139
15139
|
|
|
15140
15140
|
// ../spec/dist/index.js
|
|
15141
|
+
var MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024;
|
|
15142
|
+
var MAX_ATTACHMENTS = 10;
|
|
15143
|
+
var MAX_ATTACHMENT_DESCRIPTION_LENGTH = 1e3;
|
|
15144
|
+
var ATTACHMENT_UPLOAD_PATH = "/v1/attachments";
|
|
15145
|
+
var attachmentDescriptionSchema = external_exports.string().trim().min(1).max(MAX_ATTACHMENT_DESCRIPTION_LENGTH).describe("Optional plain text: what this file shows and why it matters.");
|
|
15146
|
+
var attachmentIdSchema = external_exports.string().regex(/^att_[a-f0-9]{32}$/);
|
|
15147
|
+
var ATTACHMENT_TARGET_TYPES = [
|
|
15148
|
+
"event",
|
|
15149
|
+
"issue",
|
|
15150
|
+
"question",
|
|
15151
|
+
"eval",
|
|
15152
|
+
"investigation",
|
|
15153
|
+
"investigation_question",
|
|
15154
|
+
"investigation_reply"
|
|
15155
|
+
];
|
|
15156
|
+
var attachmentTargetSchema = external_exports.object({
|
|
15157
|
+
type: external_exports.enum(ATTACHMENT_TARGET_TYPES),
|
|
15158
|
+
id: external_exports.string().min(1).max(64)
|
|
15159
|
+
});
|
|
15160
|
+
var attachmentManifestSchema = external_exports.object({
|
|
15161
|
+
filename: external_exports.string().min(1).max(180).refine(
|
|
15162
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: Reject control characters in filenames and HTTP headers.
|
|
15163
|
+
(name) => !/[\\/\u0000-\u001f\u007f]/.test(name) && name !== "." && name !== "..",
|
|
15164
|
+
"Use a filename without directories or control characters."
|
|
15165
|
+
),
|
|
15166
|
+
mediaType: external_exports.string().max(127).regex(/^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/),
|
|
15167
|
+
size: external_exports.number().int().min(1).max(MAX_ATTACHMENT_BYTES),
|
|
15168
|
+
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/)
|
|
15169
|
+
});
|
|
15170
|
+
var prepareAttachmentSchema = attachmentManifestSchema.extend({
|
|
15171
|
+
to: external_exports.string().min(1).max(253).optional(),
|
|
15172
|
+
scope: external_exports.enum(["reporter", "owner"]).default("reporter"),
|
|
15173
|
+
/** Self-reported agent name for reporter uploads. */
|
|
15174
|
+
uploader: external_exports.string().min(1).max(128).optional()
|
|
15175
|
+
});
|
|
15176
|
+
var preparedAttachmentSchema = external_exports.object({
|
|
15177
|
+
reference: external_exports.object({
|
|
15178
|
+
id: attachmentIdSchema,
|
|
15179
|
+
token: external_exports.string().regex(/^hva_[a-f0-9]{64}$/)
|
|
15180
|
+
}),
|
|
15181
|
+
uploadUrl: external_exports.url(),
|
|
15182
|
+
expiresAt: external_exports.string()
|
|
15183
|
+
});
|
|
15184
|
+
var attachmentReferenceSchema = preparedAttachmentSchema.shape.reference.extend({
|
|
15185
|
+
description: attachmentDescriptionSchema.optional()
|
|
15186
|
+
});
|
|
15187
|
+
var attachmentReferencesSchema = external_exports.array(attachmentReferenceSchema).max(MAX_ATTACHMENTS).refine(
|
|
15188
|
+
(refs) => new Set(refs.map((ref) => ref.id)).size === refs.length,
|
|
15189
|
+
"Each file can be attached once."
|
|
15190
|
+
);
|
|
15191
|
+
var attachFilesSchema = external_exports.object({
|
|
15192
|
+
target: attachmentTargetSchema,
|
|
15193
|
+
attachments: attachmentReferencesSchema.min(1)
|
|
15194
|
+
});
|
|
15195
|
+
var attachmentSchema = attachmentManifestSchema.extend({
|
|
15196
|
+
id: attachmentIdSchema,
|
|
15197
|
+
createdAt: external_exports.string(),
|
|
15198
|
+
source: external_exports.enum(["reporter", "owner"]),
|
|
15199
|
+
/** Reporter names are self-reported; owner uploads are authenticated. */
|
|
15200
|
+
uploader: external_exports.string().nullable(),
|
|
15201
|
+
/** The record the file belongs to — a report when shown on its issue or eval. */
|
|
15202
|
+
target: attachmentTargetSchema,
|
|
15203
|
+
description: attachmentDescriptionSchema.optional()
|
|
15204
|
+
});
|
|
15205
|
+
var deliveredAttachmentSchema = attachmentSchema.extend({
|
|
15206
|
+
url: external_exports.url(),
|
|
15207
|
+
expiresAt: external_exports.string()
|
|
15208
|
+
});
|
|
15209
|
+
var MEDIA_TYPES = {
|
|
15210
|
+
png: "image/png",
|
|
15211
|
+
jpg: "image/jpeg",
|
|
15212
|
+
jpeg: "image/jpeg",
|
|
15213
|
+
gif: "image/gif",
|
|
15214
|
+
webp: "image/webp",
|
|
15215
|
+
svg: "image/svg+xml",
|
|
15216
|
+
mp4: "video/mp4",
|
|
15217
|
+
webm: "video/webm",
|
|
15218
|
+
mp3: "audio/mpeg",
|
|
15219
|
+
m4a: "audio/mp4",
|
|
15220
|
+
wav: "audio/wav",
|
|
15221
|
+
ogg: "audio/ogg",
|
|
15222
|
+
pdf: "application/pdf",
|
|
15223
|
+
json: "application/json",
|
|
15224
|
+
jsonl: "application/x-ndjson",
|
|
15225
|
+
ndjson: "application/x-ndjson",
|
|
15226
|
+
txt: "text/plain",
|
|
15227
|
+
log: "text/plain",
|
|
15228
|
+
md: "text/markdown",
|
|
15229
|
+
csv: "text/csv",
|
|
15230
|
+
zip: "application/zip",
|
|
15231
|
+
html: "text/html"
|
|
15232
|
+
};
|
|
15233
|
+
function mediaTypeForFilename(filename) {
|
|
15234
|
+
const extension = /\.([^./\\]+)$/.exec(filename)?.[1]?.toLowerCase();
|
|
15235
|
+
return extension && MEDIA_TYPES[extension] || "application/octet-stream";
|
|
15236
|
+
}
|
|
15141
15237
|
var PROTOCOL_VERSION = 1;
|
|
15142
15238
|
var MAX_FEEDBACK_LENGTH = 5e3;
|
|
15143
15239
|
var MAX_SUBJECT_LENGTH = 500;
|
|
@@ -15157,10 +15253,18 @@ var FEEDBACK_CATEGORIES = [
|
|
|
15157
15253
|
"cli",
|
|
15158
15254
|
"api",
|
|
15159
15255
|
"model",
|
|
15160
|
-
"eval",
|
|
15161
15256
|
"ux",
|
|
15162
15257
|
"other"
|
|
15163
15258
|
];
|
|
15259
|
+
var createQuestionInputSchema = external_exports.object({
|
|
15260
|
+
prompt: external_exports.string().trim().min(8).max(500).describe('The question, e.g. "If you used <feature>: what broke or was missing?"'),
|
|
15261
|
+
category: external_exports.enum(FEEDBACK_CATEGORIES).optional().describe("Only ask agents whose submission carries this category."),
|
|
15262
|
+
attachments: attachmentReferencesSchema.optional().describe("Uploaded files, each {id, token, description?}; every agent asked can open them."),
|
|
15263
|
+
idempotencyKey: external_exports.string().regex(/^[A-Za-z0-9_-]{8,64}$/).optional().describe(
|
|
15264
|
+
"Same key + same project = the same question, so a retried publish never duplicates."
|
|
15265
|
+
)
|
|
15266
|
+
});
|
|
15267
|
+
var LEGACY_CATEGORIES = ["eval"];
|
|
15164
15268
|
var EVENT_STATUSES = [
|
|
15165
15269
|
"new",
|
|
15166
15270
|
"seen",
|
|
@@ -15169,10 +15273,20 @@ var EVENT_STATUSES = [
|
|
|
15169
15273
|
"wont_fix",
|
|
15170
15274
|
"spam"
|
|
15171
15275
|
];
|
|
15172
|
-
var ISSUE_STATUSES = [
|
|
15276
|
+
var ISSUE_STATUSES = [
|
|
15277
|
+
"open",
|
|
15278
|
+
"in_progress",
|
|
15279
|
+
"needs_review",
|
|
15280
|
+
"resolved",
|
|
15281
|
+
"wont_fix",
|
|
15282
|
+
"spam"
|
|
15283
|
+
];
|
|
15284
|
+
var issueStatusSchema = external_exports.enum(ISSUE_STATUSES);
|
|
15285
|
+
var EVAL_STATUSES = ["proposed", "accepted", "archived"];
|
|
15173
15286
|
var VENDOR_CATEGORY_PATTERN = /^x-[a-z0-9][a-z0-9-]{0,38}$/;
|
|
15174
15287
|
var categorySchema = external_exports.union([
|
|
15175
15288
|
external_exports.enum(FEEDBACK_CATEGORIES),
|
|
15289
|
+
external_exports.enum(LEGACY_CATEGORIES),
|
|
15176
15290
|
external_exports.string().regex(VENDOR_CATEGORY_PATTERN, "vendor categories must match x-<kebab-case>")
|
|
15177
15291
|
]);
|
|
15178
15292
|
var sentimentSchema = external_exports.enum(["positive", "negative", "neutral"]);
|
|
@@ -15234,6 +15348,10 @@ var feedbackEventSchema = external_exports.object({
|
|
|
15234
15348
|
author: authorSchema.optional(),
|
|
15235
15349
|
thread: external_exports.object({ id: external_exports.string().regex(THREAD_ID_PATTERN) }),
|
|
15236
15350
|
eval: evalReportSchema.optional(),
|
|
15351
|
+
/** Id of an owner/system question this submission answers (from a prior response's `ask`). */
|
|
15352
|
+
question: external_exports.string().max(64).optional(),
|
|
15353
|
+
/** Uploaded files, committed with the event or not at all. Bytes never travel in feedback JSON. */
|
|
15354
|
+
attachments: attachmentReferencesSchema.optional(),
|
|
15237
15355
|
context: feedbackContextSchema.optional(),
|
|
15238
15356
|
metadata: metadataSchema.optional(),
|
|
15239
15357
|
/** Client-minted retry key: same key + same project = same stored event. */
|
|
@@ -15244,6 +15362,31 @@ var feedbackEventSchema = external_exports.object({
|
|
|
15244
15362
|
}),
|
|
15245
15363
|
consent: external_exports.object({ telemetry: external_exports.boolean() })
|
|
15246
15364
|
});
|
|
15365
|
+
var knownIssueSchema = external_exports.object({
|
|
15366
|
+
title: external_exports.string().max(120),
|
|
15367
|
+
/** wont_fix is disclosed only when the owner attached a closing note. */
|
|
15368
|
+
status: external_exports.enum(["open", "wont_fix"]),
|
|
15369
|
+
/** This very report flipped a resolved issue back open — already recorded. */
|
|
15370
|
+
reopened: external_exports.boolean().optional(),
|
|
15371
|
+
/** Total reports on this issue, including this one. */
|
|
15372
|
+
reports: external_exports.number().int().positive(),
|
|
15373
|
+
/** The owner's closing note, verbatim — their explanation of the decision. */
|
|
15374
|
+
note: external_exports.string().max(MAX_GUIDANCE_LENGTH).optional(),
|
|
15375
|
+
/** Server-composed next step for the submitting agent. */
|
|
15376
|
+
hint: external_exports.string().max(300)
|
|
15377
|
+
});
|
|
15378
|
+
var ownerIssueSchema = external_exports.object({
|
|
15379
|
+
id: external_exports.string(),
|
|
15380
|
+
title: external_exports.string(),
|
|
15381
|
+
summary: external_exports.string().nullable(),
|
|
15382
|
+
status: issueStatusSchema,
|
|
15383
|
+
fingerprint: external_exports.string().nullable(),
|
|
15384
|
+
event_count: external_exports.number(),
|
|
15385
|
+
reopened_count: external_exports.number(),
|
|
15386
|
+
first_seen: external_exports.string(),
|
|
15387
|
+
last_seen: external_exports.string(),
|
|
15388
|
+
links_json: external_exports.string()
|
|
15389
|
+
});
|
|
15247
15390
|
var ingestResponseSchema = external_exports.object({
|
|
15248
15391
|
id: external_exports.string().max(64),
|
|
15249
15392
|
thread: external_exports.string().regex(THREAD_ID_PATTERN),
|
|
@@ -15251,6 +15394,19 @@ var ingestResponseSchema = external_exports.object({
|
|
|
15251
15394
|
resume: external_exports.string().max(512).optional(),
|
|
15252
15395
|
/** Vendor-configured answer back to the submitting agent (known issues, workarounds). */
|
|
15253
15396
|
guidance: external_exports.string().max(MAX_GUIDANCE_LENGTH).optional(),
|
|
15397
|
+
/** The report matched an already-tracked issue; recorded — don't file variants. */
|
|
15398
|
+
known_issue: knownIssueSchema.optional(),
|
|
15399
|
+
/**
|
|
15400
|
+
* A question from the project's team, delivered at most one per response.
|
|
15401
|
+
* Answering is optional and must be grounded in what the agent actually did;
|
|
15402
|
+
* `command` is ready to run and files the answer on this thread.
|
|
15403
|
+
*/
|
|
15404
|
+
ask: external_exports.object({
|
|
15405
|
+
id: external_exports.string().max(64),
|
|
15406
|
+
prompt: external_exports.string().max(500),
|
|
15407
|
+
command: external_exports.string().max(512),
|
|
15408
|
+
attachments: external_exports.array(deliveredAttachmentSchema).optional()
|
|
15409
|
+
}).optional(),
|
|
15254
15410
|
/** True when idempotencyKey matched an already-stored event; id/thread are the original's. */
|
|
15255
15411
|
duplicate: external_exports.boolean().optional()
|
|
15256
15412
|
});
|
|
@@ -15279,8 +15435,8 @@ var repoEntrySchema = external_exports.object({
|
|
|
15279
15435
|
var repoListSchema = external_exports.array(repoEntrySchema).max(20);
|
|
15280
15436
|
function formatIssues(error51) {
|
|
15281
15437
|
return error51.issues.map((issue2) => {
|
|
15282
|
-
const
|
|
15283
|
-
return
|
|
15438
|
+
const path6 = issue2.path.join(".");
|
|
15439
|
+
return path6 ? `${path6}: ${issue2.message}` : issue2.message;
|
|
15284
15440
|
});
|
|
15285
15441
|
}
|
|
15286
15442
|
function validateFeedbackEvent(input) {
|
|
@@ -15297,8 +15453,11 @@ function validateIngestResponse(input) {
|
|
|
15297
15453
|
}
|
|
15298
15454
|
|
|
15299
15455
|
// ../core/dist/index.js
|
|
15300
|
-
import {
|
|
15456
|
+
import { createHash } from "crypto";
|
|
15457
|
+
import { readFile, stat } from "fs/promises";
|
|
15301
15458
|
import path2 from "path";
|
|
15459
|
+
import { readFileSync } from "fs";
|
|
15460
|
+
import path3 from "path";
|
|
15302
15461
|
|
|
15303
15462
|
// ../../node_modules/.pnpm/agent-cli-detector@0.1.5/node_modules/agent-cli-detector/dist/index.js
|
|
15304
15463
|
import { execFileSync } from "child_process";
|
|
@@ -15662,29 +15821,152 @@ function matchesEnvSignal(signal, env) {
|
|
|
15662
15821
|
|
|
15663
15822
|
// ../core/dist/index.js
|
|
15664
15823
|
import { homedir } from "os";
|
|
15665
|
-
import
|
|
15824
|
+
import path22 from "path";
|
|
15666
15825
|
import { mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
15667
|
-
import path32 from "path";
|
|
15668
|
-
import { appendFileSync, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
15669
15826
|
import path4 from "path";
|
|
15827
|
+
import { randomUUID } from "crypto";
|
|
15828
|
+
import { appendFileSync, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync3, renameSync, rmSync } from "fs";
|
|
15829
|
+
import path5 from "path";
|
|
15670
15830
|
import { randomBytes } from "crypto";
|
|
15671
15831
|
import { createRequire } from "module";
|
|
15832
|
+
var FeedbackError = class extends Error {
|
|
15833
|
+
constructor(message) {
|
|
15834
|
+
super(message);
|
|
15835
|
+
this.name = "FeedbackError";
|
|
15836
|
+
}
|
|
15837
|
+
};
|
|
15838
|
+
async function readLocalAttachments(inputs, cwd = process.cwd()) {
|
|
15839
|
+
if (inputs.length > MAX_ATTACHMENTS)
|
|
15840
|
+
throw new FeedbackError(`At most ${MAX_ATTACHMENTS} files can be attached.`);
|
|
15841
|
+
const files = [];
|
|
15842
|
+
for (const input of inputs) {
|
|
15843
|
+
const selected = typeof input === "string" ? input : input.path;
|
|
15844
|
+
const filename = path2.basename(selected);
|
|
15845
|
+
const description = attachmentDescriptionSchema.optional().safeParse(typeof input === "string" ? void 0 : input.description);
|
|
15846
|
+
if (!description.success)
|
|
15847
|
+
throw new FeedbackError(
|
|
15848
|
+
`Invalid description for "${filename}": ${description.error.issues.map((issue2) => issue2.message).join("; ")}`
|
|
15849
|
+
);
|
|
15850
|
+
const file2 = path2.resolve(cwd, selected);
|
|
15851
|
+
const info = await stat(file2).catch(() => null);
|
|
15852
|
+
if (!info?.isFile())
|
|
15853
|
+
throw new FeedbackError(`Cannot attach "${selected}": choose an existing, readable file.`);
|
|
15854
|
+
if (info.size < 1 || info.size > MAX_ATTACHMENT_BYTES)
|
|
15855
|
+
throw new FeedbackError(`"${filename}" must be between 1 byte and 20 MiB.`);
|
|
15856
|
+
const bytes = new Uint8Array(
|
|
15857
|
+
await readFile(file2).catch(() => {
|
|
15858
|
+
throw new FeedbackError(`Cannot read "${selected}".`);
|
|
15859
|
+
})
|
|
15860
|
+
);
|
|
15861
|
+
const manifest = attachmentManifestSchema.safeParse({
|
|
15862
|
+
filename,
|
|
15863
|
+
mediaType: mediaTypeForFilename(filename),
|
|
15864
|
+
size: bytes.length,
|
|
15865
|
+
sha256: createHash("sha256").update(bytes).digest("hex")
|
|
15866
|
+
});
|
|
15867
|
+
if (!manifest.success)
|
|
15868
|
+
throw new FeedbackError(
|
|
15869
|
+
`Cannot attach "${filename}": ${manifest.error.issues.map((issue2) => issue2.message).join("; ")}`
|
|
15870
|
+
);
|
|
15871
|
+
files.push({
|
|
15872
|
+
manifest: manifest.data,
|
|
15873
|
+
bytes,
|
|
15874
|
+
...description.data ? { description: description.data } : {}
|
|
15875
|
+
});
|
|
15876
|
+
}
|
|
15877
|
+
return files;
|
|
15878
|
+
}
|
|
15879
|
+
var AttachmentUploadError = class extends FeedbackError {
|
|
15880
|
+
constructor(message, rejected) {
|
|
15881
|
+
super(message);
|
|
15882
|
+
this.rejected = rejected;
|
|
15883
|
+
this.name = "AttachmentUploadError";
|
|
15884
|
+
}
|
|
15885
|
+
rejected;
|
|
15886
|
+
};
|
|
15887
|
+
async function send(fetchImpl, url2, init, timeoutMs) {
|
|
15888
|
+
let response;
|
|
15889
|
+
try {
|
|
15890
|
+
response = await fetchImpl(url2, {
|
|
15891
|
+
...init,
|
|
15892
|
+
redirect: "error",
|
|
15893
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
15894
|
+
});
|
|
15895
|
+
} catch {
|
|
15896
|
+
throw new AttachmentUploadError("Could not reach the server to upload files.", false);
|
|
15897
|
+
}
|
|
15898
|
+
if (response.ok) return response;
|
|
15899
|
+
const body = await response.json().catch(() => null);
|
|
15900
|
+
const errors = Array.isArray(body?.errors) ? body.errors.map(String).join("; ") : void 0;
|
|
15901
|
+
if (response.status === 404 && !errors)
|
|
15902
|
+
throw new AttachmentUploadError("This server does not accept files.", false);
|
|
15903
|
+
throw new AttachmentUploadError(
|
|
15904
|
+
errors ?? `File upload failed (${response.status}).`,
|
|
15905
|
+
!(response.status >= 500 || response.status === 429 || response.status === 408)
|
|
15906
|
+
);
|
|
15907
|
+
}
|
|
15908
|
+
async function uploadFiles(options) {
|
|
15909
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
15910
|
+
const timeoutMs = options.timeoutMs ?? 6e4;
|
|
15911
|
+
const origin = new URL(options.endpoint).origin;
|
|
15912
|
+
const references = [];
|
|
15913
|
+
for (const file2 of options.files) {
|
|
15914
|
+
const response = await send(
|
|
15915
|
+
fetchImpl,
|
|
15916
|
+
`${origin}${ATTACHMENT_UPLOAD_PATH}`,
|
|
15917
|
+
{
|
|
15918
|
+
method: "POST",
|
|
15919
|
+
headers: {
|
|
15920
|
+
"content-type": "application/json",
|
|
15921
|
+
...options.secretKey ? { authorization: `Bearer ${options.secretKey}` } : {},
|
|
15922
|
+
...options.writeKey ? { [WRITE_KEY_HEADER]: options.writeKey } : {}
|
|
15923
|
+
},
|
|
15924
|
+
body: JSON.stringify({
|
|
15925
|
+
...file2.manifest,
|
|
15926
|
+
to: options.to,
|
|
15927
|
+
scope: options.secretKey ? "owner" : "reporter",
|
|
15928
|
+
uploader: options.uploader
|
|
15929
|
+
})
|
|
15930
|
+
},
|
|
15931
|
+
timeoutMs
|
|
15932
|
+
);
|
|
15933
|
+
const prepared = preparedAttachmentSchema.safeParse(await response.json().catch(() => null));
|
|
15934
|
+
if (!prepared.success || new URL(prepared.data.uploadUrl).origin !== origin)
|
|
15935
|
+
throw new AttachmentUploadError("The server returned an invalid upload response.", true);
|
|
15936
|
+
await send(
|
|
15937
|
+
fetchImpl,
|
|
15938
|
+
prepared.data.uploadUrl,
|
|
15939
|
+
{
|
|
15940
|
+
method: "PUT",
|
|
15941
|
+
headers: { authorization: `Bearer ${prepared.data.reference.token}` },
|
|
15942
|
+
body: file2.bytes
|
|
15943
|
+
},
|
|
15944
|
+
// At least 100 KB/s: a 20 MiB file on a slow link still gets about 3.5 minutes.
|
|
15945
|
+
Math.max(timeoutMs, file2.bytes.length / 100)
|
|
15946
|
+
);
|
|
15947
|
+
references.push({
|
|
15948
|
+
...prepared.data.reference,
|
|
15949
|
+
...file2.description ? { description: file2.description } : {}
|
|
15950
|
+
});
|
|
15951
|
+
}
|
|
15952
|
+
return references;
|
|
15953
|
+
}
|
|
15672
15954
|
var DSN_ENV_VAR = "HIVENET_DSN";
|
|
15673
15955
|
var REGISTRY_ENV_VAR = "HIVENET_REGISTRY";
|
|
15674
15956
|
var HOME_ENV_VAR = "HIVENET_HOME";
|
|
15675
15957
|
var NO_TELEMETRY_ENV_VAR = "HIVENET_NO_TELEMETRY";
|
|
15676
15958
|
function feedbackHomeDir(env = process.env) {
|
|
15677
15959
|
const override = env[HOME_ENV_VAR];
|
|
15678
|
-
return override?.trim() ? override :
|
|
15960
|
+
return override?.trim() ? override : path22.join(homedir(), ".hivenet");
|
|
15679
15961
|
}
|
|
15680
15962
|
function isTelemetryDisabled(extraOptOutEnvVars = [], env = process.env) {
|
|
15681
15963
|
const vars = ["DO_NOT_TRACK", NO_TELEMETRY_ENV_VAR, ...extraOptOutEnvVars];
|
|
15682
15964
|
return vars.some((name) => env[name] === "1" || env[name] === "true");
|
|
15683
15965
|
}
|
|
15684
15966
|
var MAX_SESSION_ID_LENGTH = 256;
|
|
15685
|
-
function detectAgentSafe() {
|
|
15967
|
+
function detectAgentSafe(env) {
|
|
15686
15968
|
try {
|
|
15687
|
-
const result = detectAgent();
|
|
15969
|
+
const result = detectAgent({ env });
|
|
15688
15970
|
if (result.detected && result.agent) {
|
|
15689
15971
|
return {
|
|
15690
15972
|
id: result.agent.id,
|
|
@@ -15696,9 +15978,9 @@ function detectAgentSafe() {
|
|
|
15696
15978
|
}
|
|
15697
15979
|
return void 0;
|
|
15698
15980
|
}
|
|
15699
|
-
function detectSandboxSafe() {
|
|
15981
|
+
function detectSandboxSafe(env) {
|
|
15700
15982
|
try {
|
|
15701
|
-
const result = detectSandbox();
|
|
15983
|
+
const result = detectSandbox({ env });
|
|
15702
15984
|
if (result.detected && result.sandbox) {
|
|
15703
15985
|
return {
|
|
15704
15986
|
id: result.sandbox.id,
|
|
@@ -15763,7 +16045,7 @@ function resolveSessions(sources, projectRoot, env) {
|
|
|
15763
16045
|
}
|
|
15764
16046
|
const value = "envVar" in source ? normalizeSessionId(env[source.envVar]) : normalizeSessionId(
|
|
15765
16047
|
readDotenvKey(
|
|
15766
|
-
|
|
16048
|
+
path3.resolve(projectRoot, source.dotenvFile),
|
|
15767
16049
|
source.dotenvKey ?? source.key
|
|
15768
16050
|
)
|
|
15769
16051
|
);
|
|
@@ -15779,8 +16061,8 @@ async function collectContext(options = {}) {
|
|
|
15779
16061
|
return void 0;
|
|
15780
16062
|
}
|
|
15781
16063
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
15782
|
-
const agent = detectAgentSafe();
|
|
15783
|
-
const sandbox = detectSandboxSafe();
|
|
16064
|
+
const agent = detectAgentSafe(env);
|
|
16065
|
+
const sandbox = detectSandboxSafe(env);
|
|
15784
16066
|
const ci = detectCi();
|
|
15785
16067
|
const session = resolveSessions(options.sessions ?? [], projectRoot, env);
|
|
15786
16068
|
let project;
|
|
@@ -15803,12 +16085,6 @@ async function collectContext(options = {}) {
|
|
|
15803
16085
|
function inferAuthor(context) {
|
|
15804
16086
|
return context?.agent ? "agent" : void 0;
|
|
15805
16087
|
}
|
|
15806
|
-
var FeedbackError = class extends Error {
|
|
15807
|
-
constructor(message) {
|
|
15808
|
-
super(message);
|
|
15809
|
-
this.name = "FeedbackError";
|
|
15810
|
-
}
|
|
15811
|
-
};
|
|
15812
16088
|
var CONFIG_FILE_NAME = "feedback.config.json";
|
|
15813
16089
|
var DESCRIPTOR_CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
15814
16090
|
var RESOLVE_TIMEOUT_MS = 5e3;
|
|
@@ -15833,9 +16109,9 @@ function parseDsn(dsn) {
|
|
|
15833
16109
|
};
|
|
15834
16110
|
}
|
|
15835
16111
|
function findConfigFile(startDir) {
|
|
15836
|
-
let current =
|
|
16112
|
+
let current = path4.resolve(startDir);
|
|
15837
16113
|
while (true) {
|
|
15838
|
-
const candidate =
|
|
16114
|
+
const candidate = path4.join(current, CONFIG_FILE_NAME);
|
|
15839
16115
|
try {
|
|
15840
16116
|
const raw = readFileSync2(candidate, "utf8");
|
|
15841
16117
|
const parsed = JSON.parse(raw);
|
|
@@ -15844,7 +16120,7 @@ function findConfigFile(startDir) {
|
|
|
15844
16120
|
}
|
|
15845
16121
|
} catch {
|
|
15846
16122
|
}
|
|
15847
|
-
const parent =
|
|
16123
|
+
const parent = path4.dirname(current);
|
|
15848
16124
|
if (parent === current) {
|
|
15849
16125
|
return void 0;
|
|
15850
16126
|
}
|
|
@@ -15852,7 +16128,7 @@ function findConfigFile(startDir) {
|
|
|
15852
16128
|
}
|
|
15853
16129
|
}
|
|
15854
16130
|
function cacheFilePath(cacheDir) {
|
|
15855
|
-
return
|
|
16131
|
+
return path4.join(cacheDir, "descriptors.json");
|
|
15856
16132
|
}
|
|
15857
16133
|
function readCache(cacheDir) {
|
|
15858
16134
|
try {
|
|
@@ -15977,7 +16253,7 @@ async function postEvent(options) {
|
|
|
15977
16253
|
error: error51 instanceof Error ? error51.message : String(error51)
|
|
15978
16254
|
};
|
|
15979
16255
|
}
|
|
15980
|
-
if (response.status >= 500) {
|
|
16256
|
+
if (response.status >= 500 || response.status === 429 || response.status === 408) {
|
|
15981
16257
|
return { kind: "unreachable", error: `server error (${response.status})` };
|
|
15982
16258
|
}
|
|
15983
16259
|
if (!response.ok) {
|
|
@@ -16005,13 +16281,14 @@ async function postEvent(options) {
|
|
|
16005
16281
|
}
|
|
16006
16282
|
var OUTBOX_FILE = "outbox.jsonl";
|
|
16007
16283
|
var MAX_OUTBOX_ENTRIES = 100;
|
|
16284
|
+
var STALE_CLAIM_MS = 30 * 60 * 1e3;
|
|
16008
16285
|
function outboxPath(env = process.env) {
|
|
16009
|
-
return
|
|
16286
|
+
return path5.join(feedbackHomeDir(env), OUTBOX_FILE);
|
|
16010
16287
|
}
|
|
16011
16288
|
function appendToOutbox(entry, env = process.env) {
|
|
16012
16289
|
try {
|
|
16013
16290
|
const file2 = outboxPath(env);
|
|
16014
|
-
mkdirSync2(
|
|
16291
|
+
mkdirSync2(path5.dirname(file2), { recursive: true });
|
|
16015
16292
|
appendFileSync(file2, `${JSON.stringify(entry)}
|
|
16016
16293
|
`);
|
|
16017
16294
|
return true;
|
|
@@ -16019,19 +16296,43 @@ function appendToOutbox(entry, env = process.env) {
|
|
|
16019
16296
|
return false;
|
|
16020
16297
|
}
|
|
16021
16298
|
}
|
|
16022
|
-
function
|
|
16299
|
+
function readEntries(file2) {
|
|
16023
16300
|
try {
|
|
16024
|
-
return readFileSync3(
|
|
16301
|
+
return readFileSync3(file2, "utf8").split("\n").filter((line) => line.trim()).flatMap((line) => {
|
|
16302
|
+
try {
|
|
16303
|
+
return [JSON.parse(line)];
|
|
16304
|
+
} catch {
|
|
16305
|
+
return [];
|
|
16306
|
+
}
|
|
16307
|
+
});
|
|
16025
16308
|
} catch {
|
|
16026
16309
|
return [];
|
|
16027
16310
|
}
|
|
16028
16311
|
}
|
|
16312
|
+
function claimQueue(env) {
|
|
16313
|
+
const file2 = outboxPath(env);
|
|
16314
|
+
let names;
|
|
16315
|
+
try {
|
|
16316
|
+
names = readdirSync(path5.dirname(file2));
|
|
16317
|
+
} catch {
|
|
16318
|
+
return [];
|
|
16319
|
+
}
|
|
16320
|
+
const claims = names.filter((name) => {
|
|
16321
|
+
const claimedAt = Number(/\.flushing-(\d+)-/.exec(name)?.[1]);
|
|
16322
|
+
return name.startsWith(OUTBOX_FILE) && Date.now() - claimedAt > STALE_CLAIM_MS;
|
|
16323
|
+
}).map((name) => path5.join(path5.dirname(file2), name));
|
|
16324
|
+
const fresh = `${file2}.flushing-${Date.now()}-${randomUUID()}`;
|
|
16325
|
+
try {
|
|
16326
|
+
renameSync(file2, fresh);
|
|
16327
|
+
claims.push(fresh);
|
|
16328
|
+
} catch {
|
|
16329
|
+
}
|
|
16330
|
+
return claims;
|
|
16331
|
+
}
|
|
16029
16332
|
async function flushOutbox(options = {}) {
|
|
16030
16333
|
const env = options.env ?? process.env;
|
|
16031
|
-
const
|
|
16032
|
-
|
|
16033
|
-
return { delivered: 0, remaining: 0 };
|
|
16034
|
-
}
|
|
16334
|
+
const claims = claimQueue(env);
|
|
16335
|
+
const entries = claims.flatMap(readEntries).slice(-MAX_OUTBOX_ENTRIES);
|
|
16035
16336
|
const failures = [];
|
|
16036
16337
|
let delivered = 0;
|
|
16037
16338
|
for (const entry of entries) {
|
|
@@ -16048,12 +16349,13 @@ async function flushOutbox(options = {}) {
|
|
|
16048
16349
|
failures.push(entry);
|
|
16049
16350
|
}
|
|
16050
16351
|
}
|
|
16051
|
-
|
|
16052
|
-
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16352
|
+
if (failures.every((entry) => appendToOutbox(entry, env))) {
|
|
16353
|
+
for (const claim of claims) {
|
|
16354
|
+
try {
|
|
16355
|
+
rmSync(claim, { force: true });
|
|
16356
|
+
} catch {
|
|
16357
|
+
}
|
|
16358
|
+
}
|
|
16057
16359
|
}
|
|
16058
16360
|
return { delivered, remaining: failures.length };
|
|
16059
16361
|
}
|
|
@@ -16073,10 +16375,10 @@ function ownerApi(options) {
|
|
|
16073
16375
|
const origin = (options.apiOrigin ?? new URL(DEFAULT_REGISTRY_URL).origin).replace(/\/$/, "");
|
|
16074
16376
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
16075
16377
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
16076
|
-
async function request(
|
|
16378
|
+
async function request(path6, init) {
|
|
16077
16379
|
let response;
|
|
16078
16380
|
try {
|
|
16079
|
-
response = await fetchImpl(`${origin}${
|
|
16381
|
+
response = await fetchImpl(`${origin}${path6}`, {
|
|
16080
16382
|
...init,
|
|
16081
16383
|
signal: AbortSignal.timeout(timeoutMs),
|
|
16082
16384
|
headers: {
|
|
@@ -16104,7 +16406,34 @@ function ownerApi(options) {
|
|
|
16104
16406
|
}
|
|
16105
16407
|
return body;
|
|
16106
16408
|
}
|
|
16409
|
+
async function upload(paths, cwd) {
|
|
16410
|
+
return uploadFiles({
|
|
16411
|
+
endpoint: origin,
|
|
16412
|
+
files: await readLocalAttachments(paths, cwd),
|
|
16413
|
+
secretKey: options.secretKey,
|
|
16414
|
+
fetchImpl,
|
|
16415
|
+
timeoutMs: Math.max(timeoutMs, 6e4)
|
|
16416
|
+
});
|
|
16417
|
+
}
|
|
16107
16418
|
return {
|
|
16419
|
+
/** Upload local files and attach them to a record (at most 10 files per record). */
|
|
16420
|
+
async attachFiles(target, paths, cwd) {
|
|
16421
|
+
if (!paths.length) throw new FeedbackError("Select at least one file.");
|
|
16422
|
+
const attachments = await upload(paths, cwd);
|
|
16423
|
+
return request("/v1/attachments/attach", {
|
|
16424
|
+
method: "POST",
|
|
16425
|
+
body: JSON.stringify({ target, attachments })
|
|
16426
|
+
});
|
|
16427
|
+
},
|
|
16428
|
+
/** A record's files; issues and evals include their reports' files. */
|
|
16429
|
+
async listAttachments(target, offset = 0) {
|
|
16430
|
+
return request(
|
|
16431
|
+
`/v1/attachments?${new URLSearchParams({ type: target.type, id: target.id, offset: String(offset) })}`
|
|
16432
|
+
);
|
|
16433
|
+
},
|
|
16434
|
+
async deleteAttachment(id) {
|
|
16435
|
+
return request(`/v1/attachments/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
16436
|
+
},
|
|
16108
16437
|
async listFeedback(filters = {}) {
|
|
16109
16438
|
const params = new URLSearchParams();
|
|
16110
16439
|
if (filters.status) params.set("status", filters.status);
|
|
@@ -16141,10 +16470,53 @@ function ownerApi(options) {
|
|
|
16141
16470
|
body: JSON.stringify({ status, ...note !== void 0 ? { note } : {} })
|
|
16142
16471
|
});
|
|
16143
16472
|
},
|
|
16473
|
+
async listQuestions(filters = {}) {
|
|
16474
|
+
const query = filters.status ? `?status=${filters.status}` : "";
|
|
16475
|
+
return request(`/v1/questions${query}`);
|
|
16476
|
+
},
|
|
16477
|
+
/** Files are shared with every agent that receives the question. */
|
|
16478
|
+
async createQuestion(prompt, category, options2 = {}) {
|
|
16479
|
+
const attachments = options2.files?.length ? await upload(options2.files, options2.cwd) : [];
|
|
16480
|
+
return request("/v1/questions", {
|
|
16481
|
+
method: "POST",
|
|
16482
|
+
body: JSON.stringify({
|
|
16483
|
+
prompt,
|
|
16484
|
+
...category ? { category } : {},
|
|
16485
|
+
...attachments.length ? { attachments } : {},
|
|
16486
|
+
...options2.idempotencyKey ? { idempotencyKey: options2.idempotencyKey } : {}
|
|
16487
|
+
})
|
|
16488
|
+
});
|
|
16489
|
+
},
|
|
16490
|
+
async closeQuestion(id) {
|
|
16491
|
+
return request(`/v1/questions/${encodeURIComponent(id)}`, {
|
|
16492
|
+
method: "PATCH",
|
|
16493
|
+
body: JSON.stringify({ status: "closed" })
|
|
16494
|
+
});
|
|
16495
|
+
},
|
|
16496
|
+
async listEvals(filters = {}) {
|
|
16497
|
+
const query = filters.status ? `?status=${filters.status}` : "";
|
|
16498
|
+
return request(`/v1/evals${query}`);
|
|
16499
|
+
},
|
|
16500
|
+
async getEval(id) {
|
|
16501
|
+
return request(`/v1/evals/${encodeURIComponent(id)}`);
|
|
16502
|
+
},
|
|
16503
|
+
/** Promote a failed-task report (category=eval event) into the eval corpus. */
|
|
16504
|
+
async promoteEval(eventId) {
|
|
16505
|
+
return request("/v1/evals", {
|
|
16506
|
+
method: "POST",
|
|
16507
|
+
body: JSON.stringify({ event_id: eventId })
|
|
16508
|
+
});
|
|
16509
|
+
},
|
|
16510
|
+
async setEvalStatus(id, status, note) {
|
|
16511
|
+
return request(`/v1/evals/${encodeURIComponent(id)}`, {
|
|
16512
|
+
method: "PATCH",
|
|
16513
|
+
body: JSON.stringify({ status, ...note !== void 0 ? { note } : {} })
|
|
16514
|
+
});
|
|
16515
|
+
},
|
|
16144
16516
|
/** Attach an external link (Slack message, Linear/GitHub issue, PR) to evt_… or iss_…. */
|
|
16145
16517
|
async addLink(id, url2, label) {
|
|
16146
|
-
const
|
|
16147
|
-
return request(
|
|
16518
|
+
const path6 = id.startsWith("iss_") ? `/v1/issues/${id}` : `/v1/events/${id}`;
|
|
16519
|
+
return request(path6, {
|
|
16148
16520
|
method: "PATCH",
|
|
16149
16521
|
body: JSON.stringify({ addLink: { url: url2, ...label !== void 0 ? { label } : {} } })
|
|
16150
16522
|
});
|
|
@@ -16172,9 +16544,10 @@ function resolveThreadId(resume) {
|
|
|
16172
16544
|
}
|
|
16173
16545
|
return { id: generateThreadId(), resumed: false };
|
|
16174
16546
|
}
|
|
16175
|
-
async function
|
|
16547
|
+
async function prepareFeedback(options) {
|
|
16176
16548
|
const env = options.env ?? process.env;
|
|
16177
16549
|
const cwd = options.cwd ?? process.cwd();
|
|
16550
|
+
const files = await readLocalAttachments(options.attachments ?? [], cwd);
|
|
16178
16551
|
const config2 = findConfigFile(cwd)?.config;
|
|
16179
16552
|
const resolveOptions = {
|
|
16180
16553
|
...options.to !== void 0 ? { to: options.to } : {},
|
|
@@ -16210,6 +16583,7 @@ async function sendFeedback(options) {
|
|
|
16210
16583
|
...author ? { author } : {},
|
|
16211
16584
|
thread: { id: thread.id },
|
|
16212
16585
|
...options.eval ? { eval: options.eval } : {},
|
|
16586
|
+
...options.question ? { question: options.question } : {},
|
|
16213
16587
|
...context ? { context } : {},
|
|
16214
16588
|
...options.metadata && Object.keys(options.metadata).length > 0 ? { metadata: options.metadata } : {},
|
|
16215
16589
|
// Minted before the first attempt so outbox retries replay the SAME event
|
|
@@ -16225,7 +16599,32 @@ async function sendFeedback(options) {
|
|
|
16225
16599
|
if (!validated.ok) {
|
|
16226
16600
|
throw new FeedbackError(`Invalid feedback event: ${validated.errors.join("; ")}`);
|
|
16227
16601
|
}
|
|
16228
|
-
|
|
16602
|
+
return { event: validated.data, destination, resumed: thread.resumed, files };
|
|
16603
|
+
}
|
|
16604
|
+
async function sendFeedback(options) {
|
|
16605
|
+
const env = options.env ?? process.env;
|
|
16606
|
+
const { event, destination, resumed, files } = await prepareFeedback(options);
|
|
16607
|
+
const names = files.map((file2) => file2.manifest.filename);
|
|
16608
|
+
let filesNotAttached;
|
|
16609
|
+
if (files.length) {
|
|
16610
|
+
try {
|
|
16611
|
+
event.attachments = await uploadFiles({
|
|
16612
|
+
endpoint: destination.endpoint,
|
|
16613
|
+
files,
|
|
16614
|
+
...destination.to ? { to: destination.to } : {},
|
|
16615
|
+
...destination.writeKey ? { writeKey: destination.writeKey } : {},
|
|
16616
|
+
...event.context?.agent?.id ? { uploader: event.context.agent.id } : {},
|
|
16617
|
+
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
16618
|
+
});
|
|
16619
|
+
} catch (error51) {
|
|
16620
|
+
if (!(error51 instanceof AttachmentUploadError) || error51.rejected) {
|
|
16621
|
+
throw new FeedbackError(
|
|
16622
|
+
`${error51 instanceof Error ? error51.message : String(error51)} Nothing was sent.`
|
|
16623
|
+
);
|
|
16624
|
+
}
|
|
16625
|
+
filesNotAttached = { files: names, reason: error51.message };
|
|
16626
|
+
}
|
|
16627
|
+
}
|
|
16229
16628
|
const result = await postEvent({
|
|
16230
16629
|
endpoint: destination.endpoint,
|
|
16231
16630
|
...destination.writeKey ? { writeKey: destination.writeKey } : {},
|
|
@@ -16239,12 +16638,17 @@ async function sendFeedback(options) {
|
|
|
16239
16638
|
response: result.response,
|
|
16240
16639
|
event,
|
|
16241
16640
|
destination,
|
|
16242
|
-
resumed
|
|
16641
|
+
resumed,
|
|
16642
|
+
...filesNotAttached ? { filesNotAttached } : {}
|
|
16243
16643
|
};
|
|
16244
16644
|
}
|
|
16245
16645
|
if (result.kind === "rejected") {
|
|
16246
16646
|
throw new FeedbackError(`Feedback rejected: ${result.errors.join("; ")}`);
|
|
16247
16647
|
}
|
|
16648
|
+
if (event.attachments) {
|
|
16649
|
+
delete event.attachments;
|
|
16650
|
+
filesNotAttached = { files: names, reason: result.error };
|
|
16651
|
+
}
|
|
16248
16652
|
const queued = options.outbox !== false && appendToOutbox(
|
|
16249
16653
|
{
|
|
16250
16654
|
endpoint: destination.endpoint,
|
|
@@ -16260,20 +16664,29 @@ async function sendFeedback(options) {
|
|
|
16260
16664
|
error: result.error,
|
|
16261
16665
|
event,
|
|
16262
16666
|
destination,
|
|
16263
|
-
resumed
|
|
16667
|
+
resumed,
|
|
16668
|
+
...filesNotAttached ? { filesNotAttached } : {}
|
|
16264
16669
|
};
|
|
16265
16670
|
}
|
|
16266
16671
|
|
|
16267
16672
|
export {
|
|
16268
16673
|
__toESM,
|
|
16674
|
+
external_exports,
|
|
16675
|
+
MAX_ATTACHMENTS,
|
|
16676
|
+
attachmentDescriptionSchema,
|
|
16677
|
+
ATTACHMENT_TARGET_TYPES,
|
|
16678
|
+
attachmentTargetSchema,
|
|
16269
16679
|
PROTOCOL_VERSION,
|
|
16270
16680
|
MAX_FEEDBACK_LENGTH,
|
|
16271
16681
|
WELL_KNOWN_PATH,
|
|
16272
16682
|
FEEDBACK_CATEGORIES,
|
|
16273
16683
|
EVENT_STATUSES,
|
|
16274
16684
|
ISSUE_STATUSES,
|
|
16685
|
+
EVAL_STATUSES,
|
|
16275
16686
|
sentimentSchema,
|
|
16276
16687
|
authorSchema,
|
|
16688
|
+
evalReportSchema,
|
|
16689
|
+
feedbackEventSchema,
|
|
16277
16690
|
validateFeedbackEvent,
|
|
16278
16691
|
validateDescriptor,
|
|
16279
16692
|
FeedbackError,
|
|
@@ -16284,6 +16697,7 @@ export {
|
|
|
16284
16697
|
resolveApiOrigin,
|
|
16285
16698
|
ownerApi,
|
|
16286
16699
|
generateThreadId,
|
|
16700
|
+
prepareFeedback,
|
|
16287
16701
|
sendFeedback,
|
|
16288
16702
|
require_arg
|
|
16289
16703
|
};
|