@ccpocket/bridge 1.68.2 → 1.69.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.
@@ -1737,10 +1737,24 @@ export class CodexProcess extends EventEmitter {
1737
1737
  const message = stringValue(params.message);
1738
1738
  if (!message)
1739
1739
  break;
1740
- if (isInformationalGuardianApproval(message)) {
1740
+ const approval = parseGuardianApproval(message);
1741
+ if (approval?.risk === "low" &&
1742
+ isLowRiskAllowDecision(approval.reason)) {
1741
1743
  console.debug("[codex-process] suppressed informational guardian approval notification");
1742
1744
  break;
1743
1745
  }
1746
+ if (approval &&
1747
+ (approval.risk === "medium" || approval.risk === "high")) {
1748
+ this.emitMessage({
1749
+ type: "guardian_approval",
1750
+ risk: approval.risk,
1751
+ reason: approval.reason,
1752
+ ...(approval.authorization
1753
+ ? { authorization: approval.authorization }
1754
+ : {}),
1755
+ });
1756
+ break;
1757
+ }
1744
1758
  this.emitMessage({
1745
1759
  type: "error",
1746
1760
  errorCode: "codex_warning",
@@ -3040,9 +3054,34 @@ function parseResultObject(rawResult) {
3040
3054
  return { byId: {}, byQuestion: {} };
3041
3055
  }
3042
3056
  }
3043
- function isInformationalGuardianApproval(message) {
3044
- const normalized = message.trim().replace(/\s+/g, " ").toLowerCase();
3045
- return /^automatic approval review approved\b/.test(normalized);
3057
+ function parseGuardianApproval(message) {
3058
+ const match = message
3059
+ .trim()
3060
+ .match(/^automatic approval review approved\s*\(([^)]*)\)\s*:\s*([\s\S]+)$/i);
3061
+ if (!match)
3062
+ return null;
3063
+ const metadata = new Map();
3064
+ for (const field of match[1].split(",")) {
3065
+ const separator = field.indexOf(":");
3066
+ if (separator === -1)
3067
+ continue;
3068
+ metadata.set(field.slice(0, separator).trim().toLowerCase(), field.slice(separator + 1).trim());
3069
+ }
3070
+ const risk = metadata.get("risk")?.toLowerCase();
3071
+ const reason = match[2].trim();
3072
+ if (!reason || (risk !== "low" && risk !== "medium" && risk !== "high")) {
3073
+ return null;
3074
+ }
3075
+ const authorization = metadata.get("authorization");
3076
+ return {
3077
+ risk,
3078
+ reason,
3079
+ ...(authorization ? { authorization } : {}),
3080
+ };
3081
+ }
3082
+ function isLowRiskAllowDecision(reason) {
3083
+ const normalized = reason.trim().replace(/\s+/g, " ");
3084
+ return /^auto-review returned a low[- ]risk allow decision\.?$/i.test(normalized);
3046
3085
  }
3047
3086
  function normalizeAnswerValues(value) {
3048
3087
  if (typeof value === "string") {