@sjawhar/pi-legion-envoy 5.30.4 → 5.30.5
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/dist/envoy.js +124 -23
- package/dist/legion.js +125 -24
- package/package.json +1 -1
package/dist/envoy.js
CHANGED
|
@@ -32463,6 +32463,7 @@ class DispatchServiceError extends Error {
|
|
|
32463
32463
|
current;
|
|
32464
32464
|
mismatches;
|
|
32465
32465
|
name = "DispatchServiceError";
|
|
32466
|
+
fromDispatch = true;
|
|
32466
32467
|
constructor(code, status, message, candidates, current, mismatches) {
|
|
32467
32468
|
super(message);
|
|
32468
32469
|
this.code = code;
|
|
@@ -32472,6 +32473,21 @@ class DispatchServiceError extends Error {
|
|
|
32472
32473
|
this.mismatches = mismatches;
|
|
32473
32474
|
}
|
|
32474
32475
|
}
|
|
32476
|
+
|
|
32477
|
+
class DispatchGatewayError extends DispatchServiceError {
|
|
32478
|
+
answer;
|
|
32479
|
+
advice;
|
|
32480
|
+
fromDispatch = false;
|
|
32481
|
+
transient;
|
|
32482
|
+
mayHaveReachedDispatch;
|
|
32483
|
+
constructor(status, answer, advice, message = `${answer}, so ${advice}.`) {
|
|
32484
|
+
super(`HTTP_${status}`, status, message);
|
|
32485
|
+
this.answer = answer;
|
|
32486
|
+
this.advice = advice;
|
|
32487
|
+
this.transient = transientStatus(status);
|
|
32488
|
+
this.mayHaveReachedDispatch = reachesDispatch(status);
|
|
32489
|
+
}
|
|
32490
|
+
}
|
|
32475
32491
|
function asErrorShape(value) {
|
|
32476
32492
|
return typeof value === "object" && value !== null ? value : {};
|
|
32477
32493
|
}
|
|
@@ -32485,7 +32501,7 @@ function requestSignal(signal) {
|
|
|
32485
32501
|
}
|
|
32486
32502
|
function whyNotAPage(answer) {
|
|
32487
32503
|
if (typeof answer === "string") {
|
|
32488
|
-
return
|
|
32504
|
+
return `text that is not a JSON page, ${GATEWAY_PAGE}, so a retry may succeed.`;
|
|
32489
32505
|
}
|
|
32490
32506
|
let what;
|
|
32491
32507
|
if (Array.isArray(answer)) {
|
|
@@ -32504,6 +32520,53 @@ function whyNotAPage(answer) {
|
|
|
32504
32520
|
}
|
|
32505
32521
|
return `${what}. Retrying will not help: the same request gets the same answer until that ` + "Dispatch is upgraded or fixed.";
|
|
32506
32522
|
}
|
|
32523
|
+
var GATEWAY_PAGE = "which looks like a proxy or gateway page rather than Dispatch's own answer";
|
|
32524
|
+
function gatewayAdvice(method, status) {
|
|
32525
|
+
if (!transientStatus(status)) {
|
|
32526
|
+
return "a retry gets the same answer until the Dispatch URL, or whatever answers in its place, is fixed";
|
|
32527
|
+
}
|
|
32528
|
+
if (method === "GET")
|
|
32529
|
+
return "a retry may succeed";
|
|
32530
|
+
return reachesDispatch(status) ? "the write may or may not have reached Dispatch: check whether it took effect before retrying it" : "the write did not reach Dispatch, and a retry may succeed";
|
|
32531
|
+
}
|
|
32532
|
+
function transientStatus(status) {
|
|
32533
|
+
return status >= 500 || status === 408 || status === 429;
|
|
32534
|
+
}
|
|
32535
|
+
function reachesDispatch(status) {
|
|
32536
|
+
return status >= 500;
|
|
32537
|
+
}
|
|
32538
|
+
var REDACTED = "[redacted]";
|
|
32539
|
+
var EXCERPT_SCAN_LIMIT = 64 * 1024;
|
|
32540
|
+
var BEARER_PIECE = 8;
|
|
32541
|
+
function redactBearer(text, bearer) {
|
|
32542
|
+
if (bearer === "")
|
|
32543
|
+
return text.slice(0, EXCERPT_SCAN_LIMIT);
|
|
32544
|
+
const length = Math.min(BEARER_PIECE, bearer.length);
|
|
32545
|
+
const scanned = text.slice(0, EXCERPT_SCAN_LIMIT + length - 1);
|
|
32546
|
+
const covered = new Uint8Array(scanned.length);
|
|
32547
|
+
const pieces = new Set;
|
|
32548
|
+
for (let at = 0;at + length <= bearer.length; at++)
|
|
32549
|
+
pieces.add(bearer.slice(at, at + length));
|
|
32550
|
+
for (const piece of pieces) {
|
|
32551
|
+
let found = scanned.indexOf(piece);
|
|
32552
|
+
while (found !== -1) {
|
|
32553
|
+
covered.fill(1, found, found + length);
|
|
32554
|
+
found = scanned.indexOf(piece, found + 1);
|
|
32555
|
+
}
|
|
32556
|
+
}
|
|
32557
|
+
let redacted = "";
|
|
32558
|
+
let kept = 0;
|
|
32559
|
+
for (let start = covered.indexOf(1);start !== -1; start = covered.indexOf(1, kept)) {
|
|
32560
|
+
redacted += `${scanned.slice(kept, start)}${REDACTED}`;
|
|
32561
|
+
const end = covered.indexOf(0, start);
|
|
32562
|
+
kept = end === -1 ? scanned.length : end;
|
|
32563
|
+
}
|
|
32564
|
+
return `${redacted}${scanned.slice(kept, EXCERPT_SCAN_LIMIT)}`.slice(0, EXCERPT_SCAN_LIMIT);
|
|
32565
|
+
}
|
|
32566
|
+
function excerpt(text, token) {
|
|
32567
|
+
const plain = redactBearer(text, token.trim()).replace(/<(script|style)\b[^<>]*>(?:[\s\S]*?<\/\1\s*>|[\s\S]*$)/gi, " ").replace(/<[^<>]*>/g, " ");
|
|
32568
|
+
return textHead(plain.replace(/(\bauthorization["']?\s*[:=]\s*["']?(?:(?:bearer|basic|digest|token)\s+)?)[^\s"'<>,;]+/gi, `$1${REDACTED}`).replace(/(\bbearer\s+)[^\s"'<>,;]+/gi, `$1${REDACTED}`));
|
|
32569
|
+
}
|
|
32507
32570
|
|
|
32508
32571
|
class DispatchClient {
|
|
32509
32572
|
token;
|
|
@@ -32761,22 +32824,24 @@ class DispatchClient {
|
|
|
32761
32824
|
};
|
|
32762
32825
|
if (body !== undefined)
|
|
32763
32826
|
headers["Content-Type"] = "application/json";
|
|
32764
|
-
const
|
|
32827
|
+
const url2 = this.#url(path2, query);
|
|
32828
|
+
const response = await this.fetchImpl(url2, {
|
|
32765
32829
|
method,
|
|
32766
32830
|
headers,
|
|
32767
32831
|
signal: this.#signal,
|
|
32768
32832
|
...body === undefined ? {} : { body: JSON.stringify(body) }
|
|
32769
32833
|
});
|
|
32770
|
-
return this.#response(response);
|
|
32834
|
+
return this.#response(method, url2, response);
|
|
32771
32835
|
}
|
|
32772
32836
|
async#form(method, path2, body) {
|
|
32773
|
-
const
|
|
32837
|
+
const url2 = this.#url(path2);
|
|
32838
|
+
const response = await this.fetchImpl(url2, {
|
|
32774
32839
|
method,
|
|
32775
32840
|
headers: { Accept: "application/json", Authorization: `Bearer ${this.token}` },
|
|
32776
32841
|
body,
|
|
32777
32842
|
signal: this.#signal
|
|
32778
32843
|
});
|
|
32779
|
-
return this.#response(response);
|
|
32844
|
+
return this.#response(method, url2, response);
|
|
32780
32845
|
}
|
|
32781
32846
|
#url(path2, query) {
|
|
32782
32847
|
const url2 = new URL(`${path2.map((segment) => encodeURIComponent(segment)).join("/")}`, `${this.#baseUrl}/`);
|
|
@@ -32792,7 +32857,7 @@ class DispatchClient {
|
|
|
32792
32857
|
}
|
|
32793
32858
|
return url2.toString();
|
|
32794
32859
|
}
|
|
32795
|
-
async#response(response) {
|
|
32860
|
+
async#response(method, url2, response) {
|
|
32796
32861
|
const text = await response.text();
|
|
32797
32862
|
let payload = text;
|
|
32798
32863
|
if (text && isJson(response)) {
|
|
@@ -32804,7 +32869,23 @@ class DispatchClient {
|
|
|
32804
32869
|
}
|
|
32805
32870
|
if (!response.ok) {
|
|
32806
32871
|
const error48 = asErrorShape(payload);
|
|
32807
|
-
|
|
32872
|
+
if (typeof error48.error === "string") {
|
|
32873
|
+
throw new DispatchServiceError(error48.code ?? `HTTP_${response.status}`, response.status, error48.error, error48.candidates, error48.current, error48.mismatches);
|
|
32874
|
+
}
|
|
32875
|
+
const quoted = excerpt(text, this.token);
|
|
32876
|
+
let body;
|
|
32877
|
+
if (quoted !== "") {
|
|
32878
|
+
body = `a body that is not Dispatch's error JSON (${JSON.stringify(quoted)})`;
|
|
32879
|
+
} else if (text === "") {
|
|
32880
|
+
body = "an empty body";
|
|
32881
|
+
} else {
|
|
32882
|
+
const within = text.length > EXCERPT_SCAN_LIMIT ? ` in its first ${EXCERPT_SCAN_LIMIT / 1024} KiB` : "";
|
|
32883
|
+
const size = Buffer.byteLength(text).toLocaleString("en-US");
|
|
32884
|
+
body = `a body of ${size} bytes and no readable text${within}`;
|
|
32885
|
+
}
|
|
32886
|
+
const reasonPhrase = excerpt(response.statusText, this.token);
|
|
32887
|
+
const reason = reasonPhrase === "" ? "" : ` ${reasonPhrase}`;
|
|
32888
|
+
throw new DispatchGatewayError(response.status, `${method} ${url2} answered ${response.status}${reason} with ${body}, ${GATEWAY_PAGE}`, gatewayAdvice(method, response.status));
|
|
32808
32889
|
}
|
|
32809
32890
|
return payload;
|
|
32810
32891
|
}
|
|
@@ -33524,7 +33605,7 @@ async function resolveArtifact(client, owner, artifactReference, { canonical = f
|
|
|
33524
33605
|
throw new Error("artifact is required for a project document");
|
|
33525
33606
|
}
|
|
33526
33607
|
const routed = await client.getProjectArtifact(owner.project, artifactReference).catch((error48) => {
|
|
33527
|
-
if (!(error48
|
|
33608
|
+
if (!dispatchAnswered(error48, 404))
|
|
33528
33609
|
throw error48;
|
|
33529
33610
|
return;
|
|
33530
33611
|
});
|
|
@@ -33695,12 +33776,12 @@ function referenceLines(edges) {
|
|
|
33695
33776
|
if (edges.length === 0)
|
|
33696
33777
|
return ["- none"];
|
|
33697
33778
|
return edges.map((edge) => {
|
|
33698
|
-
const
|
|
33699
|
-
return `- ${edge.kind} ${edge.node.kind} ${edge.node.ref ?? edge.node.id} (${
|
|
33779
|
+
const excerpt2 = edge.excerpt === undefined ? "" : `${textHead(edge.excerpt.text)} \xB7 `;
|
|
33780
|
+
return `- ${edge.kind} ${edge.node.kind} ${edge.node.ref ?? edge.node.id} (${excerpt2}${edge.created_at})`;
|
|
33700
33781
|
});
|
|
33701
33782
|
}
|
|
33702
33783
|
function unavailableReason(error48) {
|
|
33703
|
-
return error48
|
|
33784
|
+
return dispatchAnswered(error48, 404) ? "unavailable" : `unavailable: ${messageFor(error48)}`;
|
|
33704
33785
|
}
|
|
33705
33786
|
async function graphEdges(client, query) {
|
|
33706
33787
|
try {
|
|
@@ -33890,9 +33971,8 @@ async function openArtifactMarks(client, resolved) {
|
|
|
33890
33971
|
const marks = asks.filter((ask) => ask.state === "open" && ask.anchor?.artifact_id === resolved.artifact.id).map((ask) => `ask ${ask.id}`);
|
|
33891
33972
|
const commentsResult = await commentsResultPromise;
|
|
33892
33973
|
if (commentsResult.status === "rejected") {
|
|
33893
|
-
if (commentsResult.reason
|
|
33974
|
+
if (dispatchAnswered(commentsResult.reason, 404))
|
|
33894
33975
|
return marks;
|
|
33895
|
-
}
|
|
33896
33976
|
throw commentsResult.reason;
|
|
33897
33977
|
}
|
|
33898
33978
|
return [
|
|
@@ -33979,10 +34059,30 @@ async function refuseRemovingOpenDecisionBlocks(client, tool, resolved, ops) {
|
|
|
33979
34059
|
`));
|
|
33980
34060
|
}
|
|
33981
34061
|
function refusalWithCode(error48, suffix = "") {
|
|
34062
|
+
if (error48 instanceof DispatchGatewayError) {
|
|
34063
|
+
let told = error48.message;
|
|
34064
|
+
if (suffix !== "") {
|
|
34065
|
+
told = error48.mayHaveReachedDispatch ? `${error48.answer}${suffix}` : `${error48.answer}, so ${error48.advice}${suffix}`;
|
|
34066
|
+
}
|
|
34067
|
+
return new DispatchGatewayError(error48.status, error48.answer, error48.advice, `${error48.code}: ${told}`);
|
|
34068
|
+
}
|
|
33982
34069
|
if (!(error48 instanceof DispatchServiceError))
|
|
33983
34070
|
return error48;
|
|
33984
34071
|
return new DispatchServiceError(error48.code, error48.status, `${error48.code}: ${error48.message}${suffix}`, error48.candidates, error48.current, error48.mismatches);
|
|
33985
34072
|
}
|
|
34073
|
+
function dispatchAnswered(error48, status) {
|
|
34074
|
+
return error48 instanceof DispatchServiceError && error48.fromDispatch && error48.status === status;
|
|
34075
|
+
}
|
|
34076
|
+
function writeMayHaveLanded(error48) {
|
|
34077
|
+
if (error48 instanceof DispatchGatewayError)
|
|
34078
|
+
return error48.mayHaveReachedDispatch;
|
|
34079
|
+
return !(error48 instanceof DispatchServiceError) || error48.status >= 500;
|
|
34080
|
+
}
|
|
34081
|
+
function withAccount(error48, account) {
|
|
34082
|
+
const message = messageFor(error48);
|
|
34083
|
+
const told = /[.!?]$/.test(message) ? `${message} ${account.charAt(0).toUpperCase()}${account.slice(1)}` : `${message}; ${account}`;
|
|
34084
|
+
return new Error(told, { cause: error48 });
|
|
34085
|
+
}
|
|
33986
34086
|
async function executeDispatchTool(input) {
|
|
33987
34087
|
const configUrl = input.config.url;
|
|
33988
34088
|
const configToken = input.config.token;
|
|
@@ -34152,7 +34252,10 @@ async function executeDispatchTool(input) {
|
|
|
34152
34252
|
ref: dispatchChildRef(dispatchIssueRef(issueKey), "message", message.id)
|
|
34153
34253
|
};
|
|
34154
34254
|
} catch (error48) {
|
|
34155
|
-
|
|
34255
|
+
const told = writeMayHaveLanded(error48) ? "the reason may or may not have been posted, and the close was not sent: read the issue's messages before retrying, since retrying this call posts its reason again" : "the reason was not posted, so the close was not sent";
|
|
34256
|
+
if (error48 instanceof DispatchServiceError)
|
|
34257
|
+
throw refusalWithCode(error48, `; ${told}`);
|
|
34258
|
+
throw withAccount(error48, told);
|
|
34156
34259
|
}
|
|
34157
34260
|
}
|
|
34158
34261
|
const linked = before.external_links.map((link) => link.url);
|
|
@@ -34171,17 +34274,15 @@ async function executeDispatchTool(input) {
|
|
|
34171
34274
|
actor
|
|
34172
34275
|
});
|
|
34173
34276
|
} catch (error48) {
|
|
34174
|
-
const taken = error48
|
|
34277
|
+
const taken = dispatchAnswered(error48, 500) && newLinks.length > 0 ? `; one of ${newLinks.join(", ")} may already be linked from another issue (a URL links exactly one issue)` : "";
|
|
34175
34278
|
if (closingNote === undefined)
|
|
34176
34279
|
throw refusalWithCode(error48, taken);
|
|
34177
|
-
const
|
|
34178
|
-
const
|
|
34179
|
-
const landed =
|
|
34280
|
+
const posted = `the reason already landed as message ${closingNote.id} (${closingNote.ref})`;
|
|
34281
|
+
const fix = error48 instanceof DispatchGatewayError && error48.transient ? "" : "fix what refused the close, then ";
|
|
34282
|
+
const landed = writeMayHaveLanded(error48) ? `${posted}, and the close may or may not have taken effect. Read the issue's status before retrying: done means it closed; otherwise retry with a reason that points at message ${closingNote.id}, since retrying this call posts its reason again` : `${posted} but the issue did not close. Retrying this call posts its reason again, so ${fix}retry with a reason that points at message ${closingNote.id}`;
|
|
34180
34283
|
if (error48 instanceof DispatchServiceError)
|
|
34181
|
-
throw refusalWithCode(error48, taken
|
|
34182
|
-
throw
|
|
34183
|
-
cause: error48
|
|
34184
|
-
});
|
|
34284
|
+
throw refusalWithCode(error48, `${taken}; ${landed}`);
|
|
34285
|
+
throw withAccount(error48, landed);
|
|
34185
34286
|
}
|
|
34186
34287
|
const linkCount = `(${after.external_links.length} ${after.external_links.length === 1 ? "link" : "links"})`;
|
|
34187
34288
|
const changes = [
|
|
@@ -34785,7 +34886,7 @@ async function resolveExistingIssue(client, issueReference) {
|
|
|
34785
34886
|
try {
|
|
34786
34887
|
return await client.resolveIssue(issueReference);
|
|
34787
34888
|
} catch (error48) {
|
|
34788
|
-
if (error48
|
|
34889
|
+
if (dispatchAnswered(error48, 404)) {
|
|
34789
34890
|
throw new Error(`no Dispatch issue is linked to ${issueReference}; create it first with ` + `dispatch_issue({ external: "${issueReference}", ... })`);
|
|
34790
34891
|
}
|
|
34791
34892
|
throw error48;
|
package/dist/legion.js
CHANGED
|
@@ -31308,6 +31308,7 @@ class DispatchServiceError extends Error {
|
|
|
31308
31308
|
current;
|
|
31309
31309
|
mismatches;
|
|
31310
31310
|
name = "DispatchServiceError";
|
|
31311
|
+
fromDispatch = true;
|
|
31311
31312
|
constructor(code, status, message, candidates, current, mismatches) {
|
|
31312
31313
|
super(message);
|
|
31313
31314
|
this.code = code;
|
|
@@ -31317,6 +31318,21 @@ class DispatchServiceError extends Error {
|
|
|
31317
31318
|
this.mismatches = mismatches;
|
|
31318
31319
|
}
|
|
31319
31320
|
}
|
|
31321
|
+
|
|
31322
|
+
class DispatchGatewayError extends DispatchServiceError {
|
|
31323
|
+
answer;
|
|
31324
|
+
advice;
|
|
31325
|
+
fromDispatch = false;
|
|
31326
|
+
transient;
|
|
31327
|
+
mayHaveReachedDispatch;
|
|
31328
|
+
constructor(status, answer, advice, message = `${answer}, so ${advice}.`) {
|
|
31329
|
+
super(`HTTP_${status}`, status, message);
|
|
31330
|
+
this.answer = answer;
|
|
31331
|
+
this.advice = advice;
|
|
31332
|
+
this.transient = transientStatus(status);
|
|
31333
|
+
this.mayHaveReachedDispatch = reachesDispatch(status);
|
|
31334
|
+
}
|
|
31335
|
+
}
|
|
31320
31336
|
function asErrorShape(value) {
|
|
31321
31337
|
return typeof value === "object" && value !== null ? value : {};
|
|
31322
31338
|
}
|
|
@@ -31330,7 +31346,7 @@ function requestSignal(signal) {
|
|
|
31330
31346
|
}
|
|
31331
31347
|
function whyNotAPage(answer) {
|
|
31332
31348
|
if (typeof answer === "string") {
|
|
31333
|
-
return
|
|
31349
|
+
return `text that is not a JSON page, ${GATEWAY_PAGE}, so a retry may succeed.`;
|
|
31334
31350
|
}
|
|
31335
31351
|
let what;
|
|
31336
31352
|
if (Array.isArray(answer)) {
|
|
@@ -31349,6 +31365,53 @@ function whyNotAPage(answer) {
|
|
|
31349
31365
|
}
|
|
31350
31366
|
return `${what}. Retrying will not help: the same request gets the same answer until that ` + "Dispatch is upgraded or fixed.";
|
|
31351
31367
|
}
|
|
31368
|
+
var GATEWAY_PAGE = "which looks like a proxy or gateway page rather than Dispatch's own answer";
|
|
31369
|
+
function gatewayAdvice(method, status) {
|
|
31370
|
+
if (!transientStatus(status)) {
|
|
31371
|
+
return "a retry gets the same answer until the Dispatch URL, or whatever answers in its place, is fixed";
|
|
31372
|
+
}
|
|
31373
|
+
if (method === "GET")
|
|
31374
|
+
return "a retry may succeed";
|
|
31375
|
+
return reachesDispatch(status) ? "the write may or may not have reached Dispatch: check whether it took effect before retrying it" : "the write did not reach Dispatch, and a retry may succeed";
|
|
31376
|
+
}
|
|
31377
|
+
function transientStatus(status) {
|
|
31378
|
+
return status >= 500 || status === 408 || status === 429;
|
|
31379
|
+
}
|
|
31380
|
+
function reachesDispatch(status) {
|
|
31381
|
+
return status >= 500;
|
|
31382
|
+
}
|
|
31383
|
+
var REDACTED = "[redacted]";
|
|
31384
|
+
var EXCERPT_SCAN_LIMIT = 64 * 1024;
|
|
31385
|
+
var BEARER_PIECE = 8;
|
|
31386
|
+
function redactBearer(text, bearer) {
|
|
31387
|
+
if (bearer === "")
|
|
31388
|
+
return text.slice(0, EXCERPT_SCAN_LIMIT);
|
|
31389
|
+
const length = Math.min(BEARER_PIECE, bearer.length);
|
|
31390
|
+
const scanned = text.slice(0, EXCERPT_SCAN_LIMIT + length - 1);
|
|
31391
|
+
const covered = new Uint8Array(scanned.length);
|
|
31392
|
+
const pieces = new Set;
|
|
31393
|
+
for (let at = 0;at + length <= bearer.length; at++)
|
|
31394
|
+
pieces.add(bearer.slice(at, at + length));
|
|
31395
|
+
for (const piece of pieces) {
|
|
31396
|
+
let found = scanned.indexOf(piece);
|
|
31397
|
+
while (found !== -1) {
|
|
31398
|
+
covered.fill(1, found, found + length);
|
|
31399
|
+
found = scanned.indexOf(piece, found + 1);
|
|
31400
|
+
}
|
|
31401
|
+
}
|
|
31402
|
+
let redacted = "";
|
|
31403
|
+
let kept = 0;
|
|
31404
|
+
for (let start = covered.indexOf(1);start !== -1; start = covered.indexOf(1, kept)) {
|
|
31405
|
+
redacted += `${scanned.slice(kept, start)}${REDACTED}`;
|
|
31406
|
+
const end = covered.indexOf(0, start);
|
|
31407
|
+
kept = end === -1 ? scanned.length : end;
|
|
31408
|
+
}
|
|
31409
|
+
return `${redacted}${scanned.slice(kept, EXCERPT_SCAN_LIMIT)}`.slice(0, EXCERPT_SCAN_LIMIT);
|
|
31410
|
+
}
|
|
31411
|
+
function excerpt(text, token) {
|
|
31412
|
+
const plain = redactBearer(text, token.trim()).replace(/<(script|style)\b[^<>]*>(?:[\s\S]*?<\/\1\s*>|[\s\S]*$)/gi, " ").replace(/<[^<>]*>/g, " ");
|
|
31413
|
+
return textHead(plain.replace(/(\bauthorization["']?\s*[:=]\s*["']?(?:(?:bearer|basic|digest|token)\s+)?)[^\s"'<>,;]+/gi, `$1${REDACTED}`).replace(/(\bbearer\s+)[^\s"'<>,;]+/gi, `$1${REDACTED}`));
|
|
31414
|
+
}
|
|
31352
31415
|
|
|
31353
31416
|
class DispatchClient {
|
|
31354
31417
|
token;
|
|
@@ -31606,22 +31669,24 @@ class DispatchClient {
|
|
|
31606
31669
|
};
|
|
31607
31670
|
if (body !== undefined)
|
|
31608
31671
|
headers["Content-Type"] = "application/json";
|
|
31609
|
-
const
|
|
31672
|
+
const url2 = this.#url(path2, query);
|
|
31673
|
+
const response = await this.fetchImpl(url2, {
|
|
31610
31674
|
method,
|
|
31611
31675
|
headers,
|
|
31612
31676
|
signal: this.#signal,
|
|
31613
31677
|
...body === undefined ? {} : { body: JSON.stringify(body) }
|
|
31614
31678
|
});
|
|
31615
|
-
return this.#response(response);
|
|
31679
|
+
return this.#response(method, url2, response);
|
|
31616
31680
|
}
|
|
31617
31681
|
async#form(method, path2, body) {
|
|
31618
|
-
const
|
|
31682
|
+
const url2 = this.#url(path2);
|
|
31683
|
+
const response = await this.fetchImpl(url2, {
|
|
31619
31684
|
method,
|
|
31620
31685
|
headers: { Accept: "application/json", Authorization: `Bearer ${this.token}` },
|
|
31621
31686
|
body,
|
|
31622
31687
|
signal: this.#signal
|
|
31623
31688
|
});
|
|
31624
|
-
return this.#response(response);
|
|
31689
|
+
return this.#response(method, url2, response);
|
|
31625
31690
|
}
|
|
31626
31691
|
#url(path2, query) {
|
|
31627
31692
|
const url2 = new URL(`${path2.map((segment) => encodeURIComponent(segment)).join("/")}`, `${this.#baseUrl}/`);
|
|
@@ -31637,7 +31702,7 @@ class DispatchClient {
|
|
|
31637
31702
|
}
|
|
31638
31703
|
return url2.toString();
|
|
31639
31704
|
}
|
|
31640
|
-
async#response(response) {
|
|
31705
|
+
async#response(method, url2, response) {
|
|
31641
31706
|
const text = await response.text();
|
|
31642
31707
|
let payload = text;
|
|
31643
31708
|
if (text && isJson(response)) {
|
|
@@ -31649,7 +31714,23 @@ class DispatchClient {
|
|
|
31649
31714
|
}
|
|
31650
31715
|
if (!response.ok) {
|
|
31651
31716
|
const error48 = asErrorShape(payload);
|
|
31652
|
-
|
|
31717
|
+
if (typeof error48.error === "string") {
|
|
31718
|
+
throw new DispatchServiceError(error48.code ?? `HTTP_${response.status}`, response.status, error48.error, error48.candidates, error48.current, error48.mismatches);
|
|
31719
|
+
}
|
|
31720
|
+
const quoted = excerpt(text, this.token);
|
|
31721
|
+
let body;
|
|
31722
|
+
if (quoted !== "") {
|
|
31723
|
+
body = `a body that is not Dispatch's error JSON (${JSON.stringify(quoted)})`;
|
|
31724
|
+
} else if (text === "") {
|
|
31725
|
+
body = "an empty body";
|
|
31726
|
+
} else {
|
|
31727
|
+
const within = text.length > EXCERPT_SCAN_LIMIT ? ` in its first ${EXCERPT_SCAN_LIMIT / 1024} KiB` : "";
|
|
31728
|
+
const size = Buffer.byteLength(text).toLocaleString("en-US");
|
|
31729
|
+
body = `a body of ${size} bytes and no readable text${within}`;
|
|
31730
|
+
}
|
|
31731
|
+
const reasonPhrase = excerpt(response.statusText, this.token);
|
|
31732
|
+
const reason = reasonPhrase === "" ? "" : ` ${reasonPhrase}`;
|
|
31733
|
+
throw new DispatchGatewayError(response.status, `${method} ${url2} answered ${response.status}${reason} with ${body}, ${GATEWAY_PAGE}`, gatewayAdvice(method, response.status));
|
|
31653
31734
|
}
|
|
31654
31735
|
return payload;
|
|
31655
31736
|
}
|
|
@@ -32392,7 +32473,7 @@ async function resolveArtifact(client, owner, artifactReference, { canonical = f
|
|
|
32392
32473
|
throw new Error("artifact is required for a project document");
|
|
32393
32474
|
}
|
|
32394
32475
|
const routed = await client.getProjectArtifact(owner.project, artifactReference).catch((error48) => {
|
|
32395
|
-
if (!(error48
|
|
32476
|
+
if (!dispatchAnswered(error48, 404))
|
|
32396
32477
|
throw error48;
|
|
32397
32478
|
return;
|
|
32398
32479
|
});
|
|
@@ -32563,12 +32644,12 @@ function referenceLines(edges) {
|
|
|
32563
32644
|
if (edges.length === 0)
|
|
32564
32645
|
return ["- none"];
|
|
32565
32646
|
return edges.map((edge) => {
|
|
32566
|
-
const
|
|
32567
|
-
return `- ${edge.kind} ${edge.node.kind} ${edge.node.ref ?? edge.node.id} (${
|
|
32647
|
+
const excerpt2 = edge.excerpt === undefined ? "" : `${textHead(edge.excerpt.text)} \xB7 `;
|
|
32648
|
+
return `- ${edge.kind} ${edge.node.kind} ${edge.node.ref ?? edge.node.id} (${excerpt2}${edge.created_at})`;
|
|
32568
32649
|
});
|
|
32569
32650
|
}
|
|
32570
32651
|
function unavailableReason(error48) {
|
|
32571
|
-
return error48
|
|
32652
|
+
return dispatchAnswered(error48, 404) ? "unavailable" : `unavailable: ${messageFor(error48)}`;
|
|
32572
32653
|
}
|
|
32573
32654
|
async function graphEdges(client, query) {
|
|
32574
32655
|
try {
|
|
@@ -32758,9 +32839,8 @@ async function openArtifactMarks(client, resolved) {
|
|
|
32758
32839
|
const marks = asks.filter((ask) => ask.state === "open" && ask.anchor?.artifact_id === resolved.artifact.id).map((ask) => `ask ${ask.id}`);
|
|
32759
32840
|
const commentsResult = await commentsResultPromise;
|
|
32760
32841
|
if (commentsResult.status === "rejected") {
|
|
32761
|
-
if (commentsResult.reason
|
|
32842
|
+
if (dispatchAnswered(commentsResult.reason, 404))
|
|
32762
32843
|
return marks;
|
|
32763
|
-
}
|
|
32764
32844
|
throw commentsResult.reason;
|
|
32765
32845
|
}
|
|
32766
32846
|
return [
|
|
@@ -32847,10 +32927,30 @@ async function refuseRemovingOpenDecisionBlocks(client, tool, resolved, ops) {
|
|
|
32847
32927
|
`));
|
|
32848
32928
|
}
|
|
32849
32929
|
function refusalWithCode(error48, suffix = "") {
|
|
32930
|
+
if (error48 instanceof DispatchGatewayError) {
|
|
32931
|
+
let told = error48.message;
|
|
32932
|
+
if (suffix !== "") {
|
|
32933
|
+
told = error48.mayHaveReachedDispatch ? `${error48.answer}${suffix}` : `${error48.answer}, so ${error48.advice}${suffix}`;
|
|
32934
|
+
}
|
|
32935
|
+
return new DispatchGatewayError(error48.status, error48.answer, error48.advice, `${error48.code}: ${told}`);
|
|
32936
|
+
}
|
|
32850
32937
|
if (!(error48 instanceof DispatchServiceError))
|
|
32851
32938
|
return error48;
|
|
32852
32939
|
return new DispatchServiceError(error48.code, error48.status, `${error48.code}: ${error48.message}${suffix}`, error48.candidates, error48.current, error48.mismatches);
|
|
32853
32940
|
}
|
|
32941
|
+
function dispatchAnswered(error48, status) {
|
|
32942
|
+
return error48 instanceof DispatchServiceError && error48.fromDispatch && error48.status === status;
|
|
32943
|
+
}
|
|
32944
|
+
function writeMayHaveLanded(error48) {
|
|
32945
|
+
if (error48 instanceof DispatchGatewayError)
|
|
32946
|
+
return error48.mayHaveReachedDispatch;
|
|
32947
|
+
return !(error48 instanceof DispatchServiceError) || error48.status >= 500;
|
|
32948
|
+
}
|
|
32949
|
+
function withAccount(error48, account) {
|
|
32950
|
+
const message = messageFor(error48);
|
|
32951
|
+
const told = /[.!?]$/.test(message) ? `${message} ${account.charAt(0).toUpperCase()}${account.slice(1)}` : `${message}; ${account}`;
|
|
32952
|
+
return new Error(told, { cause: error48 });
|
|
32953
|
+
}
|
|
32854
32954
|
async function executeDispatchTool(input) {
|
|
32855
32955
|
const configUrl = input.config.url;
|
|
32856
32956
|
const configToken = input.config.token;
|
|
@@ -33020,7 +33120,10 @@ async function executeDispatchTool(input) {
|
|
|
33020
33120
|
ref: dispatchChildRef(dispatchIssueRef(issueKey), "message", message.id)
|
|
33021
33121
|
};
|
|
33022
33122
|
} catch (error48) {
|
|
33023
|
-
|
|
33123
|
+
const told = writeMayHaveLanded(error48) ? "the reason may or may not have been posted, and the close was not sent: read the issue's messages before retrying, since retrying this call posts its reason again" : "the reason was not posted, so the close was not sent";
|
|
33124
|
+
if (error48 instanceof DispatchServiceError)
|
|
33125
|
+
throw refusalWithCode(error48, `; ${told}`);
|
|
33126
|
+
throw withAccount(error48, told);
|
|
33024
33127
|
}
|
|
33025
33128
|
}
|
|
33026
33129
|
const linked = before.external_links.map((link) => link.url);
|
|
@@ -33039,17 +33142,15 @@ async function executeDispatchTool(input) {
|
|
|
33039
33142
|
actor
|
|
33040
33143
|
});
|
|
33041
33144
|
} catch (error48) {
|
|
33042
|
-
const taken = error48
|
|
33145
|
+
const taken = dispatchAnswered(error48, 500) && newLinks.length > 0 ? `; one of ${newLinks.join(", ")} may already be linked from another issue (a URL links exactly one issue)` : "";
|
|
33043
33146
|
if (closingNote === undefined)
|
|
33044
33147
|
throw refusalWithCode(error48, taken);
|
|
33045
|
-
const
|
|
33046
|
-
const
|
|
33047
|
-
const landed =
|
|
33148
|
+
const posted = `the reason already landed as message ${closingNote.id} (${closingNote.ref})`;
|
|
33149
|
+
const fix = error48 instanceof DispatchGatewayError && error48.transient ? "" : "fix what refused the close, then ";
|
|
33150
|
+
const landed = writeMayHaveLanded(error48) ? `${posted}, and the close may or may not have taken effect. Read the issue's status before retrying: done means it closed; otherwise retry with a reason that points at message ${closingNote.id}, since retrying this call posts its reason again` : `${posted} but the issue did not close. Retrying this call posts its reason again, so ${fix}retry with a reason that points at message ${closingNote.id}`;
|
|
33048
33151
|
if (error48 instanceof DispatchServiceError)
|
|
33049
|
-
throw refusalWithCode(error48, taken
|
|
33050
|
-
throw
|
|
33051
|
-
cause: error48
|
|
33052
|
-
});
|
|
33152
|
+
throw refusalWithCode(error48, `${taken}; ${landed}`);
|
|
33153
|
+
throw withAccount(error48, landed);
|
|
33053
33154
|
}
|
|
33054
33155
|
const linkCount = `(${after.external_links.length} ${after.external_links.length === 1 ? "link" : "links"})`;
|
|
33055
33156
|
const changes = [
|
|
@@ -33653,7 +33754,7 @@ async function resolveExistingIssue(client, issueReference) {
|
|
|
33653
33754
|
try {
|
|
33654
33755
|
return await client.resolveIssue(issueReference);
|
|
33655
33756
|
} catch (error48) {
|
|
33656
|
-
if (error48
|
|
33757
|
+
if (dispatchAnswered(error48, 404)) {
|
|
33657
33758
|
throw new Error(`no Dispatch issue is linked to ${issueReference}; create it first with ` + `dispatch_issue({ external: "${issueReference}", ... })`);
|
|
33658
33759
|
}
|
|
33659
33760
|
throw error48;
|
|
@@ -33702,7 +33803,7 @@ import { logger } from "@oh-my-pi/pi-utils";
|
|
|
33702
33803
|
// package.json
|
|
33703
33804
|
var package_default = {
|
|
33704
33805
|
name: "@sjawhar/pi-legion-envoy",
|
|
33705
|
-
version: "5.30.
|
|
33806
|
+
version: "5.30.5",
|
|
33706
33807
|
type: "module",
|
|
33707
33808
|
omp: {
|
|
33708
33809
|
extensions: [
|