@ubiquity-os/plugin-sdk 3.6.3 → 3.7.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/dist/configuration.d.mts +16 -11
- package/dist/configuration.d.ts +16 -11
- package/dist/configuration.js +219 -36
- package/dist/configuration.mjs +219 -36
- package/dist/{context-BbEmsEct.d.ts → context-BE4WjJZf.d.ts} +1 -0
- package/dist/{context-sqbr2o6i.d.mts → context-Ckj1HMjz.d.mts} +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +209 -124
- package/dist/index.mjs +209 -124
- package/dist/llm.d.mts +1 -1
- package/dist/llm.d.ts +1 -1
- package/dist/llm.js +46 -11
- package/dist/llm.mjs +46 -11
- package/dist/signature.js +2 -2
- package/dist/signature.mjs +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -41,7 +41,6 @@ module.exports = __toCommonJS(src_exports);
|
|
|
41
41
|
|
|
42
42
|
// src/actions.ts
|
|
43
43
|
var core = __toESM(require("@actions/core"));
|
|
44
|
-
var github2 = __toESM(require("@actions/github"));
|
|
45
44
|
var import_value3 = require("@sinclair/typebox/value");
|
|
46
45
|
|
|
47
46
|
// ../../node_modules/@ubiquity-os/ubiquity-os-logger/dist/index.js
|
|
@@ -379,8 +378,56 @@ var Logs = class _Logs {
|
|
|
379
378
|
// src/actions.ts
|
|
380
379
|
var import_dotenv = require("dotenv");
|
|
381
380
|
|
|
382
|
-
// src/
|
|
383
|
-
|
|
381
|
+
// src/error.ts
|
|
382
|
+
function getErrorStatus(err) {
|
|
383
|
+
if (!err || typeof err !== "object") return null;
|
|
384
|
+
const candidate = err;
|
|
385
|
+
const directStatus = candidate.status ?? candidate.response?.status;
|
|
386
|
+
if (typeof directStatus === "number" && Number.isFinite(directStatus)) return directStatus;
|
|
387
|
+
if (typeof directStatus === "string" && directStatus.trim()) {
|
|
388
|
+
const parsed = Number.parseInt(directStatus, 10);
|
|
389
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
390
|
+
}
|
|
391
|
+
if (err instanceof Error) {
|
|
392
|
+
const match = /LLM API error:\s*(\d{3})/i.exec(err.message);
|
|
393
|
+
if (match) {
|
|
394
|
+
const parsed = Number.parseInt(match[1], 10);
|
|
395
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
function logByStatus(context, message, metadata) {
|
|
401
|
+
const status = getErrorStatus(metadata.err);
|
|
402
|
+
const payload = { ...metadata, ...status ? { status } : {} };
|
|
403
|
+
if (status && status >= 500) return context.logger.error(message, payload);
|
|
404
|
+
if (status && status >= 400) return context.logger.warn(message, payload);
|
|
405
|
+
if (status && status >= 300) return context.logger.debug(message, payload);
|
|
406
|
+
if (status && status >= 200) return context.logger.ok(message, payload);
|
|
407
|
+
if (status && status >= 100) return context.logger.info(message, payload);
|
|
408
|
+
return context.logger.error(message, payload);
|
|
409
|
+
}
|
|
410
|
+
function transformError(context, error) {
|
|
411
|
+
if (error instanceof LogReturn) {
|
|
412
|
+
return error;
|
|
413
|
+
}
|
|
414
|
+
if (error instanceof AggregateError) {
|
|
415
|
+
const message = error.errors.map((err) => {
|
|
416
|
+
if (err instanceof LogReturn) {
|
|
417
|
+
return err.logMessage.raw;
|
|
418
|
+
}
|
|
419
|
+
if (err instanceof Error) {
|
|
420
|
+
return err.message;
|
|
421
|
+
}
|
|
422
|
+
return String(err);
|
|
423
|
+
}).join("\n\n");
|
|
424
|
+
return logByStatus(context, message, { err: error });
|
|
425
|
+
}
|
|
426
|
+
if (error instanceof Error) {
|
|
427
|
+
return logByStatus(context, error.message, { err: error });
|
|
428
|
+
}
|
|
429
|
+
return logByStatus(context, String(error), { err: error });
|
|
430
|
+
}
|
|
384
431
|
|
|
385
432
|
// ../../node_modules/hono/dist/helper/adapter/index.js
|
|
386
433
|
var env = (c, runtime) => {
|
|
@@ -432,6 +479,21 @@ var checkUserAgentEquals = (platform) => {
|
|
|
432
479
|
return userAgent.startsWith(platform);
|
|
433
480
|
};
|
|
434
481
|
|
|
482
|
+
// src/helpers/github-context.ts
|
|
483
|
+
var github = __toESM(require("@actions/github"));
|
|
484
|
+
function getGithubContext() {
|
|
485
|
+
const override = globalThis.__UOS_GITHUB_CONTEXT__;
|
|
486
|
+
if (override) {
|
|
487
|
+
return override;
|
|
488
|
+
}
|
|
489
|
+
const module2 = github;
|
|
490
|
+
const context = module2.context ?? module2.default?.context;
|
|
491
|
+
if (!context) {
|
|
492
|
+
throw new Error("GitHub context is unavailable.");
|
|
493
|
+
}
|
|
494
|
+
return context;
|
|
495
|
+
}
|
|
496
|
+
|
|
435
497
|
// src/helpers/runtime-info.ts
|
|
436
498
|
var PluginRuntimeInfo = class _PluginRuntimeInfo {
|
|
437
499
|
static _instance = null;
|
|
@@ -480,10 +542,11 @@ var CfRuntimeInfo = class extends PluginRuntimeInfo {
|
|
|
480
542
|
};
|
|
481
543
|
var NodeRuntimeInfo = class extends PluginRuntimeInfo {
|
|
482
544
|
get version() {
|
|
483
|
-
return
|
|
545
|
+
return getGithubContext().sha;
|
|
484
546
|
}
|
|
485
547
|
get runUrl() {
|
|
486
|
-
|
|
548
|
+
const context = getGithubContext();
|
|
549
|
+
return context.payload.repository ? `${context.payload.repository?.html_url}/actions/runs/${context.runId}` : "http://localhost";
|
|
487
550
|
}
|
|
488
551
|
};
|
|
489
552
|
var DenoRuntimeInfo = class extends PluginRuntimeInfo {
|
|
@@ -573,14 +636,23 @@ function getPluginOptions(options) {
|
|
|
573
636
|
}
|
|
574
637
|
|
|
575
638
|
// src/comment.ts
|
|
639
|
+
function logByStatus2(logger, message, status, metadata) {
|
|
640
|
+
const payload = { ...metadata, ...status ? { status } : {} };
|
|
641
|
+
if (status && status >= 500) return logger.error(message, payload);
|
|
642
|
+
if (status && status >= 400) return logger.warn(message, payload);
|
|
643
|
+
if (status && status >= 300) return logger.debug(message, payload);
|
|
644
|
+
if (status && status >= 200) return logger.ok(message, payload);
|
|
645
|
+
if (status && status >= 100) return logger.info(message, payload);
|
|
646
|
+
return logger.error(message, payload);
|
|
647
|
+
}
|
|
576
648
|
var CommentHandler = class _CommentHandler {
|
|
577
649
|
static HEADER_NAME = "UbiquityOS";
|
|
578
650
|
_lastCommentId = { reviewCommentId: null, issueCommentId: null };
|
|
579
|
-
async _updateIssueComment(
|
|
651
|
+
async _updateIssueComment(context, params) {
|
|
580
652
|
if (!this._lastCommentId.issueCommentId) {
|
|
581
|
-
throw
|
|
653
|
+
throw context.logger.error("issueCommentId is missing");
|
|
582
654
|
}
|
|
583
|
-
const commentData = await
|
|
655
|
+
const commentData = await context.octokit.rest.issues.updateComment({
|
|
584
656
|
owner: params.owner,
|
|
585
657
|
repo: params.repo,
|
|
586
658
|
comment_id: this._lastCommentId.issueCommentId,
|
|
@@ -588,11 +660,11 @@ var CommentHandler = class _CommentHandler {
|
|
|
588
660
|
});
|
|
589
661
|
return { ...commentData.data, issueNumber: params.issueNumber };
|
|
590
662
|
}
|
|
591
|
-
async _updateReviewComment(
|
|
663
|
+
async _updateReviewComment(context, params) {
|
|
592
664
|
if (!this._lastCommentId.reviewCommentId) {
|
|
593
|
-
throw
|
|
665
|
+
throw context.logger.error("reviewCommentId is missing");
|
|
594
666
|
}
|
|
595
|
-
const commentData = await
|
|
667
|
+
const commentData = await context.octokit.rest.pulls.updateReviewComment({
|
|
596
668
|
owner: params.owner,
|
|
597
669
|
repo: params.repo,
|
|
598
670
|
comment_id: this._lastCommentId.reviewCommentId,
|
|
@@ -600,9 +672,9 @@ var CommentHandler = class _CommentHandler {
|
|
|
600
672
|
});
|
|
601
673
|
return { ...commentData.data, issueNumber: params.issueNumber };
|
|
602
674
|
}
|
|
603
|
-
async _createNewComment(
|
|
675
|
+
async _createNewComment(context, params) {
|
|
604
676
|
if (params.commentId) {
|
|
605
|
-
const commentData2 = await
|
|
677
|
+
const commentData2 = await context.octokit.rest.pulls.createReplyForReviewComment({
|
|
606
678
|
owner: params.owner,
|
|
607
679
|
repo: params.repo,
|
|
608
680
|
pull_number: params.issueNumber,
|
|
@@ -612,7 +684,7 @@ var CommentHandler = class _CommentHandler {
|
|
|
612
684
|
this._lastCommentId.reviewCommentId = commentData2.data.id;
|
|
613
685
|
return { ...commentData2.data, issueNumber: params.issueNumber };
|
|
614
686
|
}
|
|
615
|
-
const commentData = await
|
|
687
|
+
const commentData = await context.octokit.rest.issues.createComment({
|
|
616
688
|
owner: params.owner,
|
|
617
689
|
repo: params.repo,
|
|
618
690
|
issue_number: params.issueNumber,
|
|
@@ -621,54 +693,58 @@ var CommentHandler = class _CommentHandler {
|
|
|
621
693
|
this._lastCommentId.issueCommentId = commentData.data.id;
|
|
622
694
|
return { ...commentData.data, issueNumber: params.issueNumber };
|
|
623
695
|
}
|
|
624
|
-
_getIssueNumber(
|
|
625
|
-
if ("issue" in
|
|
626
|
-
if ("pull_request" in
|
|
627
|
-
if ("discussion" in
|
|
696
|
+
_getIssueNumber(context) {
|
|
697
|
+
if ("issue" in context.payload) return context.payload.issue.number;
|
|
698
|
+
if ("pull_request" in context.payload) return context.payload.pull_request.number;
|
|
699
|
+
if ("discussion" in context.payload) return context.payload.discussion.number;
|
|
628
700
|
return void 0;
|
|
629
701
|
}
|
|
630
|
-
_getCommentId(
|
|
631
|
-
return "pull_request" in
|
|
702
|
+
_getCommentId(context) {
|
|
703
|
+
return "pull_request" in context.payload && "comment" in context.payload ? context.payload.comment.id : void 0;
|
|
632
704
|
}
|
|
633
|
-
_extractIssueContext(
|
|
634
|
-
if (!("repository" in
|
|
705
|
+
_extractIssueContext(context) {
|
|
706
|
+
if (!("repository" in context.payload) || !context.payload.repository?.owner?.login) {
|
|
635
707
|
return null;
|
|
636
708
|
}
|
|
637
|
-
const issueNumber = this._getIssueNumber(
|
|
709
|
+
const issueNumber = this._getIssueNumber(context);
|
|
638
710
|
if (!issueNumber) return null;
|
|
639
711
|
return {
|
|
640
712
|
issueNumber,
|
|
641
|
-
commentId: this._getCommentId(
|
|
642
|
-
owner:
|
|
643
|
-
repo:
|
|
713
|
+
commentId: this._getCommentId(context),
|
|
714
|
+
owner: context.payload.repository.owner.login,
|
|
715
|
+
repo: context.payload.repository.name
|
|
644
716
|
};
|
|
645
717
|
}
|
|
646
|
-
_processMessage(
|
|
718
|
+
_processMessage(context, message) {
|
|
647
719
|
if (message instanceof Error) {
|
|
648
720
|
const metadata2 = {
|
|
649
721
|
message: message.message,
|
|
650
722
|
name: message.name,
|
|
651
723
|
stack: message.stack
|
|
652
724
|
};
|
|
653
|
-
|
|
725
|
+
const status = getErrorStatus(message);
|
|
726
|
+
const logReturn = logByStatus2(context.logger, message.message, status, metadata2);
|
|
727
|
+
return { metadata: { ...metadata2, ...status ? { status } : {} }, logMessage: logReturn.logMessage };
|
|
654
728
|
}
|
|
729
|
+
const stackLine = message.metadata?.error?.stack?.split("\n")[2];
|
|
730
|
+
const callerMatch = stackLine ? /at (\S+)/.exec(stackLine) : null;
|
|
655
731
|
const metadata = message.metadata ? {
|
|
656
732
|
...message.metadata,
|
|
657
733
|
message: message.metadata.message,
|
|
658
734
|
stack: message.metadata.stack || message.metadata.error?.stack,
|
|
659
|
-
caller: message.metadata.caller ||
|
|
735
|
+
caller: message.metadata.caller || callerMatch?.[1]
|
|
660
736
|
} : { ...message };
|
|
661
737
|
return { metadata, logMessage: message.logMessage };
|
|
662
738
|
}
|
|
663
|
-
_getInstigatorName(
|
|
664
|
-
if ("installation" in
|
|
665
|
-
return
|
|
739
|
+
_getInstigatorName(context) {
|
|
740
|
+
if ("installation" in context.payload && context.payload.installation && "account" in context.payload.installation && context.payload.installation?.account?.name) {
|
|
741
|
+
return context.payload.installation?.account?.name;
|
|
666
742
|
}
|
|
667
|
-
return
|
|
743
|
+
return context.payload.sender?.login || _CommentHandler.HEADER_NAME;
|
|
668
744
|
}
|
|
669
|
-
_createMetadataContent(
|
|
745
|
+
_createMetadataContent(context, metadata) {
|
|
670
746
|
const jsonPretty = sanitizeMetadata(metadata);
|
|
671
|
-
const instigatorName = this._getInstigatorName(
|
|
747
|
+
const instigatorName = this._getInstigatorName(context);
|
|
672
748
|
const runUrl = PluginRuntimeInfo.getInstance().runUrl;
|
|
673
749
|
const version = PluginRuntimeInfo.getInstance().version;
|
|
674
750
|
const callingFnName = metadata.caller || "anonymous";
|
|
@@ -685,63 +761,39 @@ var CommentHandler = class _CommentHandler {
|
|
|
685
761
|
/*
|
|
686
762
|
* Creates the body for the comment, embeds the metadata and the header hidden in the body as well.
|
|
687
763
|
*/
|
|
688
|
-
createCommentBody(
|
|
689
|
-
return this._createCommentBody(
|
|
764
|
+
createCommentBody(context, message, options) {
|
|
765
|
+
return this._createCommentBody(context, message, options);
|
|
690
766
|
}
|
|
691
|
-
_createCommentBody(
|
|
692
|
-
const { metadata, logMessage } = this._processMessage(
|
|
693
|
-
const { header, jsonPretty } = this._createMetadataContent(
|
|
767
|
+
_createCommentBody(context, message, options) {
|
|
768
|
+
const { metadata, logMessage } = this._processMessage(context, message);
|
|
769
|
+
const { header, jsonPretty } = this._createMetadataContent(context, metadata);
|
|
694
770
|
const metadataContent = this._formatMetadataContent(logMessage, header, jsonPretty);
|
|
695
771
|
return `${options?.raw ? logMessage?.raw : logMessage?.diff}
|
|
696
772
|
|
|
697
773
|
${metadataContent}
|
|
698
774
|
`;
|
|
699
775
|
}
|
|
700
|
-
async postComment(
|
|
701
|
-
const issueContext = this._extractIssueContext(
|
|
776
|
+
async postComment(context, message, options = { updateComment: true, raw: false }) {
|
|
777
|
+
const issueContext = this._extractIssueContext(context);
|
|
702
778
|
if (!issueContext) {
|
|
703
|
-
|
|
779
|
+
context.logger.warn("Cannot post comment: missing issue context in payload");
|
|
704
780
|
return null;
|
|
705
781
|
}
|
|
706
|
-
const body = this._createCommentBody(
|
|
782
|
+
const body = this._createCommentBody(context, message, options);
|
|
707
783
|
const { issueNumber, commentId, owner, repo } = issueContext;
|
|
708
784
|
const params = { owner, repo, body, issueNumber };
|
|
709
785
|
if (options.updateComment) {
|
|
710
|
-
if (this._lastCommentId.issueCommentId && !("pull_request" in
|
|
711
|
-
return this._updateIssueComment(
|
|
786
|
+
if (this._lastCommentId.issueCommentId && !("pull_request" in context.payload && "comment" in context.payload)) {
|
|
787
|
+
return this._updateIssueComment(context, params);
|
|
712
788
|
}
|
|
713
|
-
if (this._lastCommentId.reviewCommentId && "pull_request" in
|
|
714
|
-
return this._updateReviewComment(
|
|
789
|
+
if (this._lastCommentId.reviewCommentId && "pull_request" in context.payload && "comment" in context.payload) {
|
|
790
|
+
return this._updateReviewComment(context, params);
|
|
715
791
|
}
|
|
716
792
|
}
|
|
717
|
-
return this._createNewComment(
|
|
793
|
+
return this._createNewComment(context, { ...params, commentId });
|
|
718
794
|
}
|
|
719
795
|
};
|
|
720
796
|
|
|
721
|
-
// src/error.ts
|
|
722
|
-
function transformError(context2, error) {
|
|
723
|
-
let loggerError;
|
|
724
|
-
if (error instanceof AggregateError) {
|
|
725
|
-
loggerError = context2.logger.error(
|
|
726
|
-
error.errors.map((err) => {
|
|
727
|
-
if (err instanceof LogReturn) {
|
|
728
|
-
return err.logMessage.raw;
|
|
729
|
-
} else if (err instanceof Error) {
|
|
730
|
-
return err.message;
|
|
731
|
-
} else {
|
|
732
|
-
return err;
|
|
733
|
-
}
|
|
734
|
-
}).join("\n\n"),
|
|
735
|
-
{ error }
|
|
736
|
-
);
|
|
737
|
-
} else if (error instanceof Error || error instanceof LogReturn) {
|
|
738
|
-
loggerError = error;
|
|
739
|
-
} else {
|
|
740
|
-
loggerError = context2.logger.error(String(error));
|
|
741
|
-
}
|
|
742
|
-
return loggerError;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
797
|
// src/helpers/command.ts
|
|
746
798
|
var import_value = require("@sinclair/typebox/value");
|
|
747
799
|
function getCommand(inputs, pluginOptions) {
|
|
@@ -974,7 +1026,7 @@ async function verifySignature(publicKeyPem, inputs, signature) {
|
|
|
974
1026
|
ref: inputs.ref,
|
|
975
1027
|
command: inputs.command
|
|
976
1028
|
};
|
|
977
|
-
const pemContents = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").
|
|
1029
|
+
const pemContents = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replace(/\s+/g, "");
|
|
978
1030
|
const binaryDer = Uint8Array.from(atob(pemContents), (c) => c.charCodeAt(0));
|
|
979
1031
|
const publicKey = await crypto.subtle.importKey(
|
|
980
1032
|
"spki",
|
|
@@ -1027,16 +1079,12 @@ var inputSchema = import_typebox3.Type.Object({
|
|
|
1027
1079
|
|
|
1028
1080
|
// src/actions.ts
|
|
1029
1081
|
(0, import_dotenv.config)();
|
|
1030
|
-
async function handleError(
|
|
1082
|
+
async function handleError(context, pluginOptions, error) {
|
|
1031
1083
|
console.error(error);
|
|
1032
|
-
const loggerError = transformError(
|
|
1033
|
-
|
|
1034
|
-
core.setFailed(loggerError.logMessage.diff);
|
|
1035
|
-
} else if (loggerError instanceof Error) {
|
|
1036
|
-
core.setFailed(loggerError);
|
|
1037
|
-
}
|
|
1084
|
+
const loggerError = transformError(context, error);
|
|
1085
|
+
core.setFailed(loggerError.logMessage.diff);
|
|
1038
1086
|
if (pluginOptions.postCommentOnError && loggerError) {
|
|
1039
|
-
await
|
|
1087
|
+
await context.commentHandler.postComment(context, loggerError);
|
|
1040
1088
|
}
|
|
1041
1089
|
}
|
|
1042
1090
|
async function createActionsPlugin(handler, options) {
|
|
@@ -1046,7 +1094,8 @@ async function createActionsPlugin(handler, options) {
|
|
|
1046
1094
|
core.setFailed("Error: PLUGIN_GITHUB_TOKEN env is not set");
|
|
1047
1095
|
return;
|
|
1048
1096
|
}
|
|
1049
|
-
const
|
|
1097
|
+
const githubContext = getGithubContext();
|
|
1098
|
+
const body = githubContext.payload.inputs;
|
|
1050
1099
|
const inputSchemaErrors = [...import_value3.Value.Errors(inputSchema, body)];
|
|
1051
1100
|
if (inputSchemaErrors.length) {
|
|
1052
1101
|
console.dir(inputSchemaErrors, { depth: null });
|
|
@@ -1084,7 +1133,7 @@ async function createActionsPlugin(handler, options) {
|
|
|
1084
1133
|
env2 = process.env;
|
|
1085
1134
|
}
|
|
1086
1135
|
const command = getCommand(inputs, pluginOptions);
|
|
1087
|
-
const
|
|
1136
|
+
const context = {
|
|
1088
1137
|
eventName: inputs.eventName,
|
|
1089
1138
|
payload: inputs.eventPayload,
|
|
1090
1139
|
command,
|
|
@@ -1097,20 +1146,21 @@ async function createActionsPlugin(handler, options) {
|
|
|
1097
1146
|
commentHandler: new CommentHandler()
|
|
1098
1147
|
};
|
|
1099
1148
|
try {
|
|
1100
|
-
const result = await handler(
|
|
1149
|
+
const result = await handler(context);
|
|
1101
1150
|
core.setOutput("result", result);
|
|
1102
1151
|
if (pluginOptions?.returnDataToKernel) {
|
|
1103
1152
|
await returnDataToKernel(pluginGithubToken, inputs.stateId, result);
|
|
1104
1153
|
}
|
|
1105
1154
|
} catch (error) {
|
|
1106
|
-
await handleError(
|
|
1155
|
+
await handleError(context, pluginOptions, error);
|
|
1107
1156
|
}
|
|
1108
1157
|
}
|
|
1109
1158
|
async function returnDataToKernel(repoToken, stateId, output) {
|
|
1159
|
+
const githubContext = getGithubContext();
|
|
1110
1160
|
const octokit = new customOctokit({ auth: repoToken });
|
|
1111
1161
|
await octokit.rest.repos.createDispatchEvent({
|
|
1112
|
-
owner:
|
|
1113
|
-
repo:
|
|
1162
|
+
owner: githubContext.repo.owner,
|
|
1163
|
+
repo: githubContext.repo.repo,
|
|
1114
1164
|
event_type: "return-data-to-ubiquity-os-kernel",
|
|
1115
1165
|
client_payload: {
|
|
1116
1166
|
state_id: stateId,
|
|
@@ -1177,7 +1227,7 @@ var import_value4 = require("@sinclair/typebox/value");
|
|
|
1177
1227
|
|
|
1178
1228
|
// ../../node_modules/hono/dist/compose.js
|
|
1179
1229
|
var compose = (middleware, onError, onNotFound) => {
|
|
1180
|
-
return (
|
|
1230
|
+
return (context, next) => {
|
|
1181
1231
|
let index = -1;
|
|
1182
1232
|
return dispatch(0);
|
|
1183
1233
|
async function dispatch(i) {
|
|
@@ -1190,31 +1240,31 @@ var compose = (middleware, onError, onNotFound) => {
|
|
|
1190
1240
|
let handler;
|
|
1191
1241
|
if (middleware[i]) {
|
|
1192
1242
|
handler = middleware[i][0][0];
|
|
1193
|
-
|
|
1243
|
+
context.req.routeIndex = i;
|
|
1194
1244
|
} else {
|
|
1195
1245
|
handler = i === middleware.length && next || void 0;
|
|
1196
1246
|
}
|
|
1197
1247
|
if (handler) {
|
|
1198
1248
|
try {
|
|
1199
|
-
res = await handler(
|
|
1249
|
+
res = await handler(context, () => dispatch(i + 1));
|
|
1200
1250
|
} catch (err) {
|
|
1201
1251
|
if (err instanceof Error && onError) {
|
|
1202
|
-
|
|
1203
|
-
res = await onError(err,
|
|
1252
|
+
context.error = err;
|
|
1253
|
+
res = await onError(err, context);
|
|
1204
1254
|
isError = true;
|
|
1205
1255
|
} else {
|
|
1206
1256
|
throw err;
|
|
1207
1257
|
}
|
|
1208
1258
|
}
|
|
1209
1259
|
} else {
|
|
1210
|
-
if (
|
|
1211
|
-
res = await onNotFound(
|
|
1260
|
+
if (context.finalized === false && onNotFound) {
|
|
1261
|
+
res = await onNotFound(context);
|
|
1212
1262
|
}
|
|
1213
1263
|
}
|
|
1214
|
-
if (res && (
|
|
1215
|
-
|
|
1264
|
+
if (res && (context.finalized === false || isError)) {
|
|
1265
|
+
context.res = res;
|
|
1216
1266
|
}
|
|
1217
|
-
return
|
|
1267
|
+
return context;
|
|
1218
1268
|
}
|
|
1219
1269
|
};
|
|
1220
1270
|
};
|
|
@@ -1616,7 +1666,7 @@ var raw = (value, callbacks) => {
|
|
|
1616
1666
|
escapedString.callbacks = callbacks;
|
|
1617
1667
|
return escapedString;
|
|
1618
1668
|
};
|
|
1619
|
-
var resolveCallback = async (str, phase, preserveCallbacks,
|
|
1669
|
+
var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => {
|
|
1620
1670
|
if (typeof str === "object" && !(str instanceof String)) {
|
|
1621
1671
|
if (!(str instanceof Promise)) {
|
|
1622
1672
|
str = str.toString();
|
|
@@ -1634,9 +1684,9 @@ var resolveCallback = async (str, phase, preserveCallbacks, context2, buffer) =>
|
|
|
1634
1684
|
} else {
|
|
1635
1685
|
buffer = [str];
|
|
1636
1686
|
}
|
|
1637
|
-
const resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context
|
|
1687
|
+
const resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context }))).then(
|
|
1638
1688
|
(res) => Promise.all(
|
|
1639
|
-
res.filter(Boolean).map((str2) => resolveCallback(str2, phase, false,
|
|
1689
|
+
res.filter(Boolean).map((str2) => resolveCallback(str2, phase, false, context, buffer))
|
|
1640
1690
|
).then(() => buffer[0])
|
|
1641
1691
|
);
|
|
1642
1692
|
if (preserveCallbacks) {
|
|
@@ -2029,13 +2079,13 @@ var Hono = class {
|
|
|
2029
2079
|
const composed = compose(matchResult[0], this.errorHandler, this.#notFoundHandler);
|
|
2030
2080
|
return (async () => {
|
|
2031
2081
|
try {
|
|
2032
|
-
const
|
|
2033
|
-
if (!
|
|
2082
|
+
const context = await composed(c);
|
|
2083
|
+
if (!context.finalized) {
|
|
2034
2084
|
throw new Error(
|
|
2035
2085
|
"Context is not finalized. Did you forget to return a Response object or `await next()`?"
|
|
2036
2086
|
);
|
|
2037
2087
|
}
|
|
2038
|
-
return
|
|
2088
|
+
return context.res;
|
|
2039
2089
|
} catch (err) {
|
|
2040
2090
|
return this.#handleError(err, c);
|
|
2041
2091
|
}
|
|
@@ -2094,7 +2144,7 @@ var Node = class {
|
|
|
2094
2144
|
#index;
|
|
2095
2145
|
#varIndex;
|
|
2096
2146
|
#children = /* @__PURE__ */ Object.create(null);
|
|
2097
|
-
insert(tokens, index, paramMap,
|
|
2147
|
+
insert(tokens, index, paramMap, context, pathErrorCheckOnly) {
|
|
2098
2148
|
if (tokens.length === 0) {
|
|
2099
2149
|
if (this.#index !== void 0) {
|
|
2100
2150
|
throw PATH_ERROR;
|
|
@@ -2132,7 +2182,7 @@ var Node = class {
|
|
|
2132
2182
|
}
|
|
2133
2183
|
node = this.#children[regexpStr] = new Node();
|
|
2134
2184
|
if (name !== "") {
|
|
2135
|
-
node.#varIndex =
|
|
2185
|
+
node.#varIndex = context.varIndex++;
|
|
2136
2186
|
}
|
|
2137
2187
|
}
|
|
2138
2188
|
if (!pathErrorCheckOnly && name !== "") {
|
|
@@ -2152,7 +2202,7 @@ var Node = class {
|
|
|
2152
2202
|
node = this.#children[token] = new Node();
|
|
2153
2203
|
}
|
|
2154
2204
|
}
|
|
2155
|
-
node.insert(restTokens, index, paramMap,
|
|
2205
|
+
node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly);
|
|
2156
2206
|
}
|
|
2157
2207
|
buildRegExpStr() {
|
|
2158
2208
|
const childKeys = Object.keys(this.#children).sort(compareKey);
|
|
@@ -2694,11 +2744,11 @@ var HTTPException = class extends Error {
|
|
|
2694
2744
|
};
|
|
2695
2745
|
|
|
2696
2746
|
// src/server.ts
|
|
2697
|
-
async function handleError2(
|
|
2747
|
+
async function handleError2(context, pluginOptions, error) {
|
|
2698
2748
|
console.error(error);
|
|
2699
|
-
const loggerError = transformError(
|
|
2749
|
+
const loggerError = transformError(context, error);
|
|
2700
2750
|
if (pluginOptions.postCommentOnError && loggerError) {
|
|
2701
|
-
await
|
|
2751
|
+
await context.commentHandler.postComment(context, loggerError);
|
|
2702
2752
|
}
|
|
2703
2753
|
throw new HTTPException(500, { message: "Unexpected error" });
|
|
2704
2754
|
}
|
|
@@ -2749,7 +2799,7 @@ function createPlugin(handler, manifest, options) {
|
|
|
2749
2799
|
const workerName = new URL(inputs.ref).hostname.split(".")[0];
|
|
2750
2800
|
PluginRuntimeInfo.getInstance({ ...env2, CLOUDFLARE_WORKER_NAME: workerName });
|
|
2751
2801
|
const command = getCommand(inputs, pluginOptions);
|
|
2752
|
-
const
|
|
2802
|
+
const context = {
|
|
2753
2803
|
eventName: inputs.eventName,
|
|
2754
2804
|
payload: inputs.eventPayload,
|
|
2755
2805
|
command,
|
|
@@ -2762,10 +2812,10 @@ function createPlugin(handler, manifest, options) {
|
|
|
2762
2812
|
commentHandler: new CommentHandler()
|
|
2763
2813
|
};
|
|
2764
2814
|
try {
|
|
2765
|
-
const result = await handler(
|
|
2815
|
+
const result = await handler(context);
|
|
2766
2816
|
return ctx.json({ stateId: inputs.stateId, output: result ?? {} });
|
|
2767
2817
|
} catch (error) {
|
|
2768
|
-
await handleError2(
|
|
2818
|
+
await handleError2(context, pluginOptions, error);
|
|
2769
2819
|
}
|
|
2770
2820
|
});
|
|
2771
2821
|
return app;
|
|
@@ -2780,6 +2830,14 @@ function normalizeBaseUrl(baseUrl) {
|
|
|
2780
2830
|
}
|
|
2781
2831
|
return normalized;
|
|
2782
2832
|
}
|
|
2833
|
+
var MAX_LLM_RETRIES = 2;
|
|
2834
|
+
var RETRY_BACKOFF_MS = [250, 750];
|
|
2835
|
+
function getRetryDelayMs(attempt) {
|
|
2836
|
+
return RETRY_BACKOFF_MS[Math.min(attempt, RETRY_BACKOFF_MS.length - 1)] ?? 750;
|
|
2837
|
+
}
|
|
2838
|
+
function sleep(ms) {
|
|
2839
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2840
|
+
}
|
|
2783
2841
|
function getEnvString(name) {
|
|
2784
2842
|
if (typeof process === "undefined" || !process?.env) return EMPTY_STRING;
|
|
2785
2843
|
return String(process.env[name] ?? EMPTY_STRING).trim();
|
|
@@ -2794,7 +2852,11 @@ function getAiBaseUrl(options) {
|
|
|
2794
2852
|
}
|
|
2795
2853
|
async function callLlm(options, input) {
|
|
2796
2854
|
const authToken = String(input.authToken ?? EMPTY_STRING).trim();
|
|
2797
|
-
if (!authToken)
|
|
2855
|
+
if (!authToken) {
|
|
2856
|
+
const err = new Error("Missing authToken in input");
|
|
2857
|
+
err.status = 401;
|
|
2858
|
+
throw err;
|
|
2859
|
+
}
|
|
2798
2860
|
const kernelToken = "ubiquityKernelToken" in input ? input.ubiquityKernelToken : void 0;
|
|
2799
2861
|
const payload = getPayload(input);
|
|
2800
2862
|
const { owner, repo, installationId } = getRepoMetadata(payload);
|
|
@@ -2814,13 +2876,7 @@ async function callLlm(options, input) {
|
|
|
2814
2876
|
installationId,
|
|
2815
2877
|
ubiquityKernelToken: kernelToken
|
|
2816
2878
|
});
|
|
2817
|
-
const response = await
|
|
2818
|
-
if (!response.ok) {
|
|
2819
|
-
const err = await response.text();
|
|
2820
|
-
const error = new Error(`LLM API error: ${response.status} - ${err}`);
|
|
2821
|
-
error.status = response.status;
|
|
2822
|
-
throw error;
|
|
2823
|
-
}
|
|
2879
|
+
const response = await fetchWithRetry(url, { method: "POST", headers, body }, MAX_LLM_RETRIES);
|
|
2824
2880
|
if (isStream) {
|
|
2825
2881
|
if (!response.body) {
|
|
2826
2882
|
throw new Error("LLM API error: missing response body for streaming request");
|
|
@@ -2832,17 +2888,46 @@ async function callLlm(options, input) {
|
|
|
2832
2888
|
function ensureKernelToken(authToken, kernelToken) {
|
|
2833
2889
|
const isKernelTokenRequired = authToken.startsWith("gh");
|
|
2834
2890
|
if (isKernelTokenRequired && !kernelToken) {
|
|
2835
|
-
|
|
2891
|
+
const err = new Error("Missing ubiquityKernelToken in input (kernel attestation is required for GitHub auth)");
|
|
2892
|
+
err.status = 401;
|
|
2893
|
+
throw err;
|
|
2836
2894
|
}
|
|
2837
2895
|
}
|
|
2838
2896
|
function ensureMessages(messages) {
|
|
2839
2897
|
if (!Array.isArray(messages) || messages.length === 0) {
|
|
2840
|
-
|
|
2898
|
+
const err = new Error("messages must be a non-empty array");
|
|
2899
|
+
err.status = 400;
|
|
2900
|
+
throw err;
|
|
2841
2901
|
}
|
|
2842
2902
|
}
|
|
2843
2903
|
function buildAiUrl(options, baseUrl) {
|
|
2844
2904
|
return `${getAiBaseUrl({ ...options, baseUrl })}/v1/chat/completions`;
|
|
2845
2905
|
}
|
|
2906
|
+
async function fetchWithRetry(url, options, maxRetries) {
|
|
2907
|
+
let attempt = 0;
|
|
2908
|
+
let lastError;
|
|
2909
|
+
while (attempt <= maxRetries) {
|
|
2910
|
+
try {
|
|
2911
|
+
const response = await fetch(url, options);
|
|
2912
|
+
if (response.ok) return response;
|
|
2913
|
+
const errText = await response.text();
|
|
2914
|
+
if (response.status >= 500 && attempt < maxRetries) {
|
|
2915
|
+
await sleep(getRetryDelayMs(attempt));
|
|
2916
|
+
attempt += 1;
|
|
2917
|
+
continue;
|
|
2918
|
+
}
|
|
2919
|
+
const error = new Error(`LLM API error: ${response.status} - ${errText}`);
|
|
2920
|
+
error.status = response.status;
|
|
2921
|
+
throw error;
|
|
2922
|
+
} catch (error) {
|
|
2923
|
+
lastError = error;
|
|
2924
|
+
if (attempt >= maxRetries) throw error;
|
|
2925
|
+
await sleep(getRetryDelayMs(attempt));
|
|
2926
|
+
attempt += 1;
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
throw lastError ?? new Error("LLM API error: request failed after retries");
|
|
2930
|
+
}
|
|
2846
2931
|
function getPayload(input) {
|
|
2847
2932
|
if ("payload" in input) {
|
|
2848
2933
|
return input.payload;
|
|
@@ -2904,7 +2989,7 @@ function getEventData(event) {
|
|
|
2904
2989
|
if (!event.trim()) return null;
|
|
2905
2990
|
const dataLines = event.split("\n").filter((line) => line.startsWith("data:"));
|
|
2906
2991
|
if (!dataLines.length) return null;
|
|
2907
|
-
const data = dataLines.map((line) => line.startsWith("data: ") ? line.slice(6) : line.slice(5).replace(/^ /,
|
|
2992
|
+
const data = dataLines.map((line) => line.startsWith("data: ") ? line.slice(6) : line.slice(5).replace(/^ /, EMPTY_STRING)).join("\n");
|
|
2908
2993
|
return data || null;
|
|
2909
2994
|
}
|
|
2910
2995
|
function parseEventData(data) {
|