@probelabs/visor 0.1.131 → 0.1.132

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.
Files changed (116) hide show
  1. package/README.md +460 -596
  2. package/action.yml +2 -2
  3. package/dist/ai-review-service.d.ts +3 -0
  4. package/dist/ai-review-service.d.ts.map +1 -1
  5. package/dist/cli-main.d.ts.map +1 -1
  6. package/dist/config/config-watcher.d.ts +15 -1
  7. package/dist/config/config-watcher.d.ts.map +1 -1
  8. package/dist/enterprise/policy/policy-input-builder.d.ts +2 -0
  9. package/dist/enterprise/policy/policy-input-builder.d.ts.map +1 -1
  10. package/dist/frontends/slack-frontend.d.ts.map +1 -1
  11. package/dist/generated/config-schema.d.ts +404 -96
  12. package/dist/generated/config-schema.d.ts.map +1 -1
  13. package/dist/generated/config-schema.json +2875 -0
  14. package/dist/index.js +23064 -8507
  15. package/dist/{traces/run-2026-02-15T19-14-20-379Z.ndjson → output/traces/run-2026-02-18T11-06-48-673Z.ndjson} +84 -84
  16. package/dist/{traces/run-2026-02-15T19-15-09-410Z.ndjson → output/traces/run-2026-02-18T11-07-37-310Z.ndjson} +1017 -1017
  17. package/dist/providers/ai-check-provider.d.ts +12 -0
  18. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  19. package/dist/providers/workflow-check-provider.d.ts.map +1 -1
  20. package/dist/providers/workflow-tool-executor.d.ts +5 -1
  21. package/dist/providers/workflow-tool-executor.d.ts.map +1 -1
  22. package/dist/sdk/{check-provider-registry-S7BMQ2FC.mjs → check-provider-registry-4WLTLPMU.mjs} +6 -6
  23. package/dist/sdk/{check-provider-registry-ZOLEYDKM.mjs → check-provider-registry-7TCA3NSG.mjs} +6 -6
  24. package/dist/sdk/{check-provider-registry-AAPPJ4CP.mjs → check-provider-registry-RRUZHGJI.mjs} +6 -6
  25. package/dist/sdk/{chunk-OMFPM576.mjs → chunk-27RV5RR2.mjs} +2 -2
  26. package/dist/sdk/{chunk-6ZZ4DPAA.mjs → chunk-5VY5QJTY.mjs} +231 -42
  27. package/dist/sdk/chunk-5VY5QJTY.mjs.map +1 -0
  28. package/dist/sdk/{chunk-2GCSK3PD.mjs → chunk-BGBXLPLL.mjs} +3 -3
  29. package/dist/sdk/{chunk-LDFUW34H.mjs → chunk-BOGVSF57.mjs} +231 -42
  30. package/dist/sdk/chunk-BOGVSF57.mjs.map +1 -0
  31. package/dist/sdk/{chunk-EBTD2D4L.mjs → chunk-FAKITJ3J.mjs} +2 -2
  32. package/dist/sdk/{chunk-RI77TA6V.mjs → chunk-LMJNI6RM.mjs} +4 -4
  33. package/dist/sdk/chunk-LMJNI6RM.mjs.map +1 -0
  34. package/dist/sdk/{chunk-LQ5B4T6L.mjs → chunk-U3BLLEW3.mjs} +431 -82
  35. package/dist/sdk/chunk-U3BLLEW3.mjs.map +1 -0
  36. package/dist/sdk/{chunk-VO4N6TEL.mjs → chunk-UBDHAGYY.mjs} +3 -3
  37. package/dist/sdk/{chunk-N4I6ZDCJ.mjs → chunk-VG7FWDC2.mjs} +3 -3
  38. package/dist/sdk/{chunk-RI77TA6V.mjs.map → chunk-VG7FWDC2.mjs.map} +1 -1
  39. package/dist/sdk/{chunk-MQ57AB4U.mjs → chunk-XGI47XIH.mjs} +260 -55
  40. package/dist/sdk/chunk-XGI47XIH.mjs.map +1 -0
  41. package/dist/sdk/{config-4EG7IQIU.mjs → config-FMIIATKX.mjs} +2 -2
  42. package/dist/sdk/{failure-condition-evaluator-GLHZZF47.mjs → failure-condition-evaluator-MUUAK7MN.mjs} +3 -3
  43. package/dist/sdk/{failure-condition-evaluator-KN55WXRO.mjs → failure-condition-evaluator-PNONVBXD.mjs} +3 -3
  44. package/dist/sdk/{github-frontend-F4TE2JY7.mjs → github-frontend-DWF6BLZH.mjs} +3 -3
  45. package/dist/sdk/{github-frontend-HCOKL53D.mjs → github-frontend-WR4S3NG5.mjs} +3 -3
  46. package/dist/sdk/{host-SAT6RHDX.mjs → host-S3LSWESP.mjs} +3 -3
  47. package/dist/sdk/{host-VA3ET7N6.mjs → host-U7V54J2H.mjs} +3 -3
  48. package/dist/sdk/{routing-KFYQGOYU.mjs → routing-F4FOWVKF.mjs} +4 -4
  49. package/dist/sdk/{routing-OXQKETSA.mjs → routing-MVDVJDYJ.mjs} +4 -4
  50. package/dist/sdk/{schedule-tool-handler-OQF57URO.mjs → schedule-tool-handler-7DNEGDZC.mjs} +6 -6
  51. package/dist/sdk/{schedule-tool-handler-PJVKWSYX.mjs → schedule-tool-handler-FRN3KKRM.mjs} +6 -6
  52. package/dist/sdk/{schedule-tool-handler-G353DHS6.mjs → schedule-tool-handler-VFES42DD.mjs} +6 -6
  53. package/dist/sdk/sdk.d.mts +56 -38
  54. package/dist/sdk/sdk.d.ts +56 -38
  55. package/dist/sdk/sdk.js +744 -115
  56. package/dist/sdk/sdk.js.map +1 -1
  57. package/dist/sdk/sdk.mjs +5 -5
  58. package/dist/sdk/{slack-frontend-LAY45IBR.mjs → slack-frontend-JS2VAZWB.mjs} +95 -4
  59. package/dist/sdk/slack-frontend-JS2VAZWB.mjs.map +1 -0
  60. package/dist/sdk/{trace-helpers-R2ETIEC2.mjs → trace-helpers-KSPGA24B.mjs} +2 -2
  61. package/dist/sdk/{trace-helpers-LOPBHYYX.mjs → trace-helpers-RDPXIN4S.mjs} +2 -2
  62. package/dist/sdk/{workflow-check-provider-LRWD52WN.mjs → workflow-check-provider-4NFWH6YO.mjs} +6 -6
  63. package/dist/sdk/{workflow-check-provider-N2DRFQDB.mjs → workflow-check-provider-BMVJ6X7N.mjs} +6 -6
  64. package/dist/sdk/{workflow-check-provider-57KAR4Y4.mjs → workflow-check-provider-CPGIRZMH.mjs} +6 -6
  65. package/dist/slack/adapter.d.ts +2 -0
  66. package/dist/slack/adapter.d.ts.map +1 -1
  67. package/dist/slack/client.d.ts +3 -0
  68. package/dist/slack/client.d.ts.map +1 -1
  69. package/dist/slack/markdown.d.ts +29 -0
  70. package/dist/slack/markdown.d.ts.map +1 -1
  71. package/dist/slack/socket-runner.d.ts +2 -0
  72. package/dist/slack/socket-runner.d.ts.map +1 -1
  73. package/dist/{output/traces/run-2026-02-15T19-14-20-379Z.ndjson → traces/run-2026-02-18T11-06-48-673Z.ndjson} +84 -84
  74. package/dist/{output/traces/run-2026-02-15T19-15-09-410Z.ndjson → traces/run-2026-02-18T11-07-37-310Z.ndjson} +1017 -1017
  75. package/dist/tui/chat-tui.d.ts +7 -0
  76. package/dist/tui/chat-tui.d.ts.map +1 -1
  77. package/dist/tui/components/input-bar.d.ts +11 -0
  78. package/dist/tui/components/input-bar.d.ts.map +1 -1
  79. package/dist/tui/components/trace-viewer.d.ts +25 -1
  80. package/dist/tui/components/trace-viewer.d.ts.map +1 -1
  81. package/dist/types/bot.d.ts +12 -0
  82. package/dist/types/bot.d.ts.map +1 -1
  83. package/dist/types/config.d.ts +4 -1
  84. package/dist/types/config.d.ts.map +1 -1
  85. package/package.json +3 -3
  86. package/dist/defaults/.visor.yaml +0 -420
  87. package/dist/sdk/chunk-6ZZ4DPAA.mjs.map +0 -1
  88. package/dist/sdk/chunk-LDFUW34H.mjs.map +0 -1
  89. package/dist/sdk/chunk-LQ5B4T6L.mjs.map +0 -1
  90. package/dist/sdk/chunk-MQ57AB4U.mjs.map +0 -1
  91. package/dist/sdk/chunk-N4I6ZDCJ.mjs.map +0 -1
  92. package/dist/sdk/slack-frontend-LAY45IBR.mjs.map +0 -1
  93. /package/dist/sdk/{check-provider-registry-AAPPJ4CP.mjs.map → check-provider-registry-4WLTLPMU.mjs.map} +0 -0
  94. /package/dist/sdk/{check-provider-registry-S7BMQ2FC.mjs.map → check-provider-registry-7TCA3NSG.mjs.map} +0 -0
  95. /package/dist/sdk/{check-provider-registry-ZOLEYDKM.mjs.map → check-provider-registry-RRUZHGJI.mjs.map} +0 -0
  96. /package/dist/sdk/{chunk-EBTD2D4L.mjs.map → chunk-27RV5RR2.mjs.map} +0 -0
  97. /package/dist/sdk/{chunk-2GCSK3PD.mjs.map → chunk-BGBXLPLL.mjs.map} +0 -0
  98. /package/dist/sdk/{chunk-OMFPM576.mjs.map → chunk-FAKITJ3J.mjs.map} +0 -0
  99. /package/dist/sdk/{chunk-VO4N6TEL.mjs.map → chunk-UBDHAGYY.mjs.map} +0 -0
  100. /package/dist/sdk/{config-4EG7IQIU.mjs.map → config-FMIIATKX.mjs.map} +0 -0
  101. /package/dist/sdk/{failure-condition-evaluator-GLHZZF47.mjs.map → failure-condition-evaluator-MUUAK7MN.mjs.map} +0 -0
  102. /package/dist/sdk/{failure-condition-evaluator-KN55WXRO.mjs.map → failure-condition-evaluator-PNONVBXD.mjs.map} +0 -0
  103. /package/dist/sdk/{github-frontend-F4TE2JY7.mjs.map → github-frontend-DWF6BLZH.mjs.map} +0 -0
  104. /package/dist/sdk/{github-frontend-HCOKL53D.mjs.map → github-frontend-WR4S3NG5.mjs.map} +0 -0
  105. /package/dist/sdk/{host-SAT6RHDX.mjs.map → host-S3LSWESP.mjs.map} +0 -0
  106. /package/dist/sdk/{host-VA3ET7N6.mjs.map → host-U7V54J2H.mjs.map} +0 -0
  107. /package/dist/sdk/{routing-KFYQGOYU.mjs.map → routing-F4FOWVKF.mjs.map} +0 -0
  108. /package/dist/sdk/{routing-OXQKETSA.mjs.map → routing-MVDVJDYJ.mjs.map} +0 -0
  109. /package/dist/sdk/{schedule-tool-handler-G353DHS6.mjs.map → schedule-tool-handler-7DNEGDZC.mjs.map} +0 -0
  110. /package/dist/sdk/{schedule-tool-handler-OQF57URO.mjs.map → schedule-tool-handler-FRN3KKRM.mjs.map} +0 -0
  111. /package/dist/sdk/{schedule-tool-handler-PJVKWSYX.mjs.map → schedule-tool-handler-VFES42DD.mjs.map} +0 -0
  112. /package/dist/sdk/{trace-helpers-LOPBHYYX.mjs.map → trace-helpers-KSPGA24B.mjs.map} +0 -0
  113. /package/dist/sdk/{trace-helpers-R2ETIEC2.mjs.map → trace-helpers-RDPXIN4S.mjs.map} +0 -0
  114. /package/dist/sdk/{workflow-check-provider-57KAR4Y4.mjs.map → workflow-check-provider-4NFWH6YO.mjs.map} +0 -0
  115. /package/dist/sdk/{workflow-check-provider-LRWD52WN.mjs.map → workflow-check-provider-BMVJ6X7N.mjs.map} +0 -0
  116. /package/dist/sdk/{workflow-check-provider-N2DRFQDB.mjs.map → workflow-check-provider-CPGIRZMH.mjs.map} +0 -0
@@ -28,7 +28,7 @@ import {
28
28
  import {
29
29
  config_exports,
30
30
  init_config
31
- } from "./chunk-LQ5B4T6L.mjs";
31
+ } from "./chunk-U3BLLEW3.mjs";
32
32
  import {
33
33
  ExecutionJournal,
34
34
  checkLoopBudget,
@@ -37,11 +37,11 @@ import {
37
37
  init_routing,
38
38
  init_snapshot_store,
39
39
  snapshot_store_exports
40
- } from "./chunk-VO4N6TEL.mjs";
40
+ } from "./chunk-BGBXLPLL.mjs";
41
41
  import {
42
42
  FailureConditionEvaluator,
43
43
  init_failure_condition_evaluator
44
- } from "./chunk-OMFPM576.mjs";
44
+ } from "./chunk-27RV5RR2.mjs";
45
45
  import {
46
46
  addEvent,
47
47
  emitNdjsonFallback,
@@ -52,7 +52,7 @@ import {
52
52
  setSpanAttributes,
53
53
  trace_helpers_exports,
54
54
  withActiveSpan
55
- } from "./chunk-RI77TA6V.mjs";
55
+ } from "./chunk-VG7FWDC2.mjs";
56
56
  import {
57
57
  addDiagramBlock,
58
58
  init_metrics
@@ -1049,7 +1049,7 @@ ${this.escapeXml(processedFallbackDiff)}
1049
1049
  <user>${this.escapeXml(String(m.user || ""))}</user>
1050
1050
  <text>${this.escapeXml(String(m.text || ""))}</text>
1051
1051
  <timestamp>${this.escapeXml(String(m.timestamp || ""))}</timestamp>
1052
- <origin>${this.escapeXml(String(m.origin || ""))}</origin>
1052
+ <origin>${this.escapeXml(String(m.origin || ""))}</origin>${this.formatFilesXml(m.files)}
1053
1053
  </message>`;
1054
1054
  }
1055
1055
  xml += `
@@ -1061,7 +1061,7 @@ ${this.escapeXml(processedFallbackDiff)}
1061
1061
  <user>${this.escapeXml(String(current.user || ""))}</user>
1062
1062
  <text>${this.escapeXml(String(current.text || ""))}</text>
1063
1063
  <timestamp>${this.escapeXml(String(current.timestamp || ""))}</timestamp>
1064
- <origin>${this.escapeXml(String(current.origin || ""))}</origin>
1064
+ <origin>${this.escapeXml(String(current.origin || ""))}</origin>${this.formatFilesXml(current.files)}
1065
1065
  </current>
1066
1066
  </slack_context>`;
1067
1067
  return xml;
@@ -1069,6 +1069,25 @@ ${this.escapeXml(processedFallbackDiff)}
1069
1069
  return "";
1070
1070
  }
1071
1071
  }
1072
+ /** Render file attachment metadata as XML fragment for a message. */
1073
+ formatFilesXml(files) {
1074
+ if (!Array.isArray(files) || files.length === 0) return "";
1075
+ let xml = `
1076
+ <files>`;
1077
+ for (const f of files) {
1078
+ xml += `
1079
+ <file>
1080
+ <name>${this.escapeXml(String(f.name || ""))}</name>
1081
+ <mimetype>${this.escapeXml(String(f.mimetype || ""))}</mimetype>
1082
+ <filetype>${this.escapeXml(String(f.filetype || ""))}</filetype>
1083
+ <url>${this.escapeXml(String(f.url_private || f.permalink || ""))}</url>
1084
+ <size>${f.size || 0}</size>
1085
+ </file>`;
1086
+ }
1087
+ xml += `
1088
+ </files>`;
1089
+ return xml;
1090
+ }
1072
1091
  /**
1073
1092
  * Build a normalized ConversationContext for GitHub (PR/issue + comments)
1074
1093
  * using the same contract as Slack's ConversationContext. This is exposed
@@ -1574,6 +1593,9 @@ ${"=".repeat(60)}
1574
1593
  if (this.config.enableTasks !== void 0) {
1575
1594
  options.enableTasks = this.config.enableTasks;
1576
1595
  }
1596
+ if (this.config.enableExecutePlan !== void 0) {
1597
+ options.enableExecutePlan = this.config.enableExecutePlan;
1598
+ }
1577
1599
  if (this.config.retry) {
1578
1600
  options.retry = this.config.retry;
1579
1601
  }
@@ -2021,7 +2043,22 @@ ${"=".repeat(60)}
2021
2043
  log("\u{1F4CB} Full response preview:", response);
2022
2044
  }
2023
2045
  try {
2024
- let reviewData;
2046
+ let reviewData = void 0;
2047
+ const RAW_OUTPUT_RE = /\n<<<RAW_OUTPUT>>>\n([\s\S]*?)\n<<<END_RAW_OUTPUT>>>/g;
2048
+ const rawOutputBlocks = [];
2049
+ let responseForParsing = response;
2050
+ {
2051
+ let rawMatch;
2052
+ while ((rawMatch = RAW_OUTPUT_RE.exec(response)) !== null) {
2053
+ rawOutputBlocks.push(rawMatch[1]);
2054
+ }
2055
+ if (rawOutputBlocks.length > 0) {
2056
+ responseForParsing = response.replace(RAW_OUTPUT_RE, "");
2057
+ log(
2058
+ `\u{1F4E6} Extracted ${rawOutputBlocks.length} RAW_OUTPUT blocks (${rawOutputBlocks.reduce((s, b) => s + b.length, 0)} chars) from response`
2059
+ );
2060
+ }
2061
+ }
2025
2062
  if (_schema === "plain" || !_schema) {
2026
2063
  log(
2027
2064
  `\u{1F4CB} ${_schema === "plain" ? "Plain" : "No"} schema detected - treating raw response as text output`
@@ -2038,7 +2075,7 @@ ${"=".repeat(60)}
2038
2075
  }
2039
2076
  {
2040
2077
  log("\u{1F50D} Extracting JSON from AI response...");
2041
- const sanitizedResponse = response.replace(/^\uFEFF/, "").replace(/[\u200B-\u200D\uFEFF\u00A0]/g, "").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "").trim();
2078
+ const sanitizedResponse = responseForParsing.replace(/^\uFEFF/, "").replace(/[\u200B-\u200D\uFEFF\u00A0]/g, "").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "").trim();
2042
2079
  try {
2043
2080
  reviewData = JSON.parse(sanitizedResponse);
2044
2081
  log("\u2705 Successfully parsed direct JSON response");
@@ -2046,22 +2083,48 @@ ${"=".repeat(60)}
2046
2083
  } catch (parseErr) {
2047
2084
  const errMsg = parseErr instanceof Error ? parseErr.message : String(parseErr);
2048
2085
  log(`\u{1F50D} Direct JSON parsing failed: ${errMsg}`);
2049
- if (response.toLowerCase().includes("i cannot") || response.toLowerCase().includes("unable to")) {
2050
- console.error("\u{1F6AB} AI refused to analyze - returning refusal as output");
2051
- const trimmed2 = response.trim();
2086
+ let recovered = false;
2087
+ const trailingMatch = errMsg.match(/after JSON at position (\d+)/);
2088
+ if (trailingMatch) {
2089
+ const pos = parseInt(trailingMatch[1], 10);
2090
+ try {
2091
+ reviewData = JSON.parse(sanitizedResponse.substring(0, pos));
2092
+ const trailing = sanitizedResponse.substring(pos).trim();
2093
+ if (trailing && reviewData && typeof reviewData === "object" && typeof reviewData.text === "string") {
2094
+ reviewData.text = reviewData.text + "\n\n" + trailing;
2095
+ log(
2096
+ `\u2705 Recovered JSON and appended ${trailing.length} chars of trailing content to text field`
2097
+ );
2098
+ } else {
2099
+ log(`\u2705 Recovered JSON by trimming trailing content at position ${pos}`);
2100
+ }
2101
+ if (debugInfo) debugInfo.jsonParseSuccess = true;
2102
+ recovered = true;
2103
+ } catch {
2104
+ }
2105
+ }
2106
+ if (!recovered) {
2107
+ if (response.toLowerCase().includes("i cannot") || response.toLowerCase().includes("unable to")) {
2108
+ console.error("\u{1F6AB} AI refused to analyze - returning refusal as output");
2109
+ const trimmed2 = responseForParsing.trim();
2110
+ const out = trimmed2 ? { text: trimmed2 } : {};
2111
+ if (rawOutputBlocks.length > 0) out._rawOutput = rawOutputBlocks.join("\n\n");
2112
+ return {
2113
+ issues: [],
2114
+ output: out,
2115
+ debug: debugInfo
2116
+ };
2117
+ }
2118
+ log("\u{1F527} Treating response as plain text (no JSON extraction)");
2119
+ const trimmed = responseForParsing.trim();
2120
+ const fallbackOut = { text: trimmed };
2121
+ if (rawOutputBlocks.length > 0) fallbackOut._rawOutput = rawOutputBlocks.join("\n\n");
2052
2122
  return {
2053
2123
  issues: [],
2054
- output: trimmed2 ? { text: trimmed2 } : {},
2124
+ output: fallbackOut,
2055
2125
  debug: debugInfo
2056
2126
  };
2057
2127
  }
2058
- log("\u{1F527} Treating response as plain text (no JSON extraction)");
2059
- const trimmed = response.trim();
2060
- return {
2061
- issues: [],
2062
- output: { text: trimmed },
2063
- debug: debugInfo
2064
- };
2065
2128
  }
2066
2129
  }
2067
2130
  const looksLikeTextOutput = reviewData && typeof reviewData === "object" && typeof reviewData.text === "string" && String(reviewData.text).trim().length > 0;
@@ -2109,6 +2172,9 @@ ${"=".repeat(60)}
2109
2172
  out.text = fallbackText;
2110
2173
  }
2111
2174
  }
2175
+ if (rawOutputBlocks.length > 0) {
2176
+ out._rawOutput = rawOutputBlocks.join("\n\n");
2177
+ }
2112
2178
  const result2 = {
2113
2179
  // Keep issues empty for custom-schema rendering; consumers read from output.*
2114
2180
  issues: [],
@@ -2956,7 +3022,7 @@ function workflowInputsToJsonSchema(inputs) {
2956
3022
  required: required.length > 0 ? required : void 0
2957
3023
  };
2958
3024
  }
2959
- function createWorkflowToolDefinition(workflow, argsOverrides) {
3025
+ function createWorkflowToolDefinition(workflow, argsOverrides, nameOverride) {
2960
3026
  const baseSchema = workflowInputsToJsonSchema(workflow.inputs);
2961
3027
  let inputSchema = baseSchema;
2962
3028
  if (argsOverrides && baseSchema && typeof baseSchema === "object") {
@@ -2974,7 +3040,7 @@ function createWorkflowToolDefinition(workflow, argsOverrides) {
2974
3040
  };
2975
3041
  }
2976
3042
  return {
2977
- name: workflow.id,
3043
+ name: nameOverride || workflow.id,
2978
3044
  description: workflow.description || `Execute the ${workflow.name} workflow`,
2979
3045
  inputSchema,
2980
3046
  // Workflow tools don't have an exec command - they're executed specially
@@ -3002,7 +3068,7 @@ async function executeWorkflowAsTool(workflowId, args, context2, argsOverrides)
3002
3068
  ...args,
3003
3069
  ...argsOverrides
3004
3070
  };
3005
- const { WorkflowCheckProvider: WorkflowCheckProvider2 } = await import("./workflow-check-provider-N2DRFQDB.mjs");
3071
+ const { WorkflowCheckProvider: WorkflowCheckProvider2 } = await import("./workflow-check-provider-CPGIRZMH.mjs");
3006
3072
  const provider = new WorkflowCheckProvider2();
3007
3073
  const checkConfig = {
3008
3074
  type: "workflow",
@@ -3024,6 +3090,16 @@ async function executeWorkflowAsTool(workflowId, args, context2, argsOverrides)
3024
3090
  );
3025
3091
  logger.debug(`[WorkflowToolExecutor] Workflow '${workflowId}' output preview: ${outputPreview}`);
3026
3092
  if (output !== void 0) {
3093
+ if (output && typeof output === "object" && typeof output._rawOutput === "string") {
3094
+ const rawOutput = output._rawOutput;
3095
+ const cleanOutput = { ...output };
3096
+ delete cleanOutput._rawOutput;
3097
+ const jsonStr = JSON.stringify(cleanOutput, null, 2);
3098
+ logger.debug(
3099
+ `[WorkflowToolExecutor] Wrapping _rawOutput (${rawOutput.length} chars) in RAW_OUTPUT delimiters for '${workflowId}'`
3100
+ );
3101
+ return jsonStr + "\n<<<RAW_OUTPUT>>>\n" + rawOutput + "\n<<<END_RAW_OUTPUT>>>";
3102
+ }
3027
3103
  return output;
3028
3104
  }
3029
3105
  if (result.content) {
@@ -3048,7 +3124,7 @@ function resolveWorkflowToolFromItem(item) {
3048
3124
  logger.warn(`[WorkflowToolExecutor] Workflow '${item.workflow}' not found in registry`);
3049
3125
  return void 0;
3050
3126
  }
3051
- return createWorkflowToolDefinition(workflow, item.args);
3127
+ return createWorkflowToolDefinition(workflow, item.args, item.name);
3052
3128
  }
3053
3129
  return void 0;
3054
3130
  }
@@ -8714,7 +8790,7 @@ async function executeCheckWithForEachItems2(checkId, forEachParent, forEachItem
8714
8790
  }
8715
8791
  }
8716
8792
  try {
8717
- const { evaluateTransitions } = await import("./routing-KFYQGOYU.mjs");
8793
+ const { evaluateTransitions } = await import("./routing-F4FOWVKF.mjs");
8718
8794
  const transTarget = await evaluateTransitions(
8719
8795
  onFinish.transitions,
8720
8796
  forEachParent,
@@ -8774,7 +8850,7 @@ async function executeCheckWithForEachItems2(checkId, forEachParent, forEachItem
8774
8850
  `[LevelDispatch] Error evaluating on_finish transitions for ${forEachParent}: ${e instanceof Error ? e.message : String(e)}`
8775
8851
  );
8776
8852
  }
8777
- const { evaluateGoto: evaluateGoto2 } = await import("./routing-KFYQGOYU.mjs");
8853
+ const { evaluateGoto: evaluateGoto2 } = await import("./routing-F4FOWVKF.mjs");
8778
8854
  if (context2.debug) {
8779
8855
  logger.info(
8780
8856
  `[LevelDispatch] Evaluating on_finish.goto_js for forEach parent: ${forEachParent}`
@@ -10030,7 +10106,7 @@ async function renderTemplateContent2(checkId, checkConfig, reviewSummary) {
10030
10106
  const fs11 = await import("fs/promises");
10031
10107
  const path14 = await import("path");
10032
10108
  const schemaRaw = checkConfig.schema || "plain";
10033
- const schema = typeof schemaRaw === "string" ? schemaRaw : "code-review";
10109
+ const schema = typeof schemaRaw === "string" && !schemaRaw.includes("{{") && !schemaRaw.includes("{%") ? schemaRaw : typeof schemaRaw === "object" ? "code-review" : "plain";
10034
10110
  let templateContent;
10035
10111
  if (checkConfig.template && checkConfig.template.content) {
10036
10112
  templateContent = String(checkConfig.template.content);
@@ -11947,7 +12023,7 @@ var init_state_machine_execution_engine = __esm({
11947
12023
  try {
11948
12024
  const map = options?.webhookContext?.webhookData;
11949
12025
  if (map) {
11950
- const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-S7BMQ2FC.mjs");
12026
+ const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-4WLTLPMU.mjs");
11951
12027
  const reg = CheckProviderRegistry2.getInstance();
11952
12028
  const p = reg.getProvider("http_input");
11953
12029
  if (p && typeof p.setWebhookContext === "function") p.setWebhookContext(map);
@@ -12060,7 +12136,7 @@ var init_state_machine_execution_engine = __esm({
12060
12136
  logger.info("[StateMachine] Using state machine engine");
12061
12137
  }
12062
12138
  if (!config) {
12063
- const { ConfigManager } = await import("./config-4EG7IQIU.mjs");
12139
+ const { ConfigManager } = await import("./config-FMIIATKX.mjs");
12064
12140
  const configManager = new ConfigManager();
12065
12141
  config = await configManager.getDefaultConfig();
12066
12142
  logger.debug("[StateMachine] Using default configuration (no config provided)");
@@ -12125,7 +12201,7 @@ var init_state_machine_execution_engine = __esm({
12125
12201
  try {
12126
12202
  const webhookData = this.executionContext?.webhookContext?.webhookData;
12127
12203
  if (webhookData instanceof Map) {
12128
- const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-G353DHS6.mjs");
12204
+ const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-FRN3KKRM.mjs");
12129
12205
  const slackCtx = extractSlackContext2(webhookData);
12130
12206
  if (slackCtx) {
12131
12207
  const payload = Array.from(webhookData.values())[0];
@@ -12154,7 +12230,7 @@ var init_state_machine_execution_engine = __esm({
12154
12230
  if (Array.isArray(configWithTagFilter.frontends) && configWithTagFilter.frontends.length > 0) {
12155
12231
  try {
12156
12232
  const { EventBus } = await import("./event-bus-5K3Y2FCS.mjs");
12157
- const { FrontendsHost } = await import("./host-SAT6RHDX.mjs");
12233
+ const { FrontendsHost } = await import("./host-U7V54J2H.mjs");
12158
12234
  const bus = new EventBus();
12159
12235
  context2.eventBus = bus;
12160
12236
  frontendsHost = new FrontendsHost(bus, logger);
@@ -12504,9 +12580,9 @@ var init_state_machine_execution_engine = __esm({
12504
12580
  * @returns Array of failure condition evaluation results
12505
12581
  */
12506
12582
  async evaluateFailureConditions(checkName, reviewSummary, config, previousOutputs, authorAssociation) {
12507
- const { FailureConditionEvaluator: FailureConditionEvaluator2 } = await import("./failure-condition-evaluator-KN55WXRO.mjs");
12583
+ const { FailureConditionEvaluator: FailureConditionEvaluator2 } = await import("./failure-condition-evaluator-PNONVBXD.mjs");
12508
12584
  const evaluator = new FailureConditionEvaluator2();
12509
- const { addEvent: addEvent3 } = await import("./trace-helpers-LOPBHYYX.mjs");
12585
+ const { addEvent: addEvent3 } = await import("./trace-helpers-RDPXIN4S.mjs");
12510
12586
  const { addFailIfTriggered } = await import("./metrics-I6A7IHG4.mjs");
12511
12587
  const checkConfig = config.checks?.[checkName];
12512
12588
  if (!checkConfig) {
@@ -13617,7 +13693,7 @@ var init_ai_check_provider = __esm({
13617
13693
  init_sandbox();
13618
13694
  init_schedule_tool();
13619
13695
  init_schedule_tool_handler();
13620
- AICheckProvider = class extends CheckProvider {
13696
+ AICheckProvider = class _AICheckProvider extends CheckProvider {
13621
13697
  aiReviewService;
13622
13698
  liquidEngine;
13623
13699
  sandbox = null;
@@ -14199,6 +14275,9 @@ ${preview}`);
14199
14275
  if (aiAny2.enableTasks !== void 0) {
14200
14276
  aiConfig.enableTasks = aiAny2.enableTasks;
14201
14277
  }
14278
+ if (aiAny2.enableExecutePlan !== void 0) {
14279
+ aiConfig.enableExecutePlan = aiAny2.enableExecutePlan;
14280
+ }
14202
14281
  if (aiAny2.allowEdit !== void 0) {
14203
14282
  aiConfig.allowEdit = aiAny2.allowEdit;
14204
14283
  }
@@ -14344,13 +14423,10 @@ ${preview}`);
14344
14423
  if (decision.capabilities.allowEdit === false) aiConfig.allowEdit = false;
14345
14424
  if (decision.capabilities.allowBash === false) aiConfig.allowBash = false;
14346
14425
  if (decision.capabilities.allowedTools) {
14347
- if (aiConfig.allowedTools) {
14348
- aiConfig.allowedTools = aiConfig.allowedTools.filter(
14349
- (t) => decision.capabilities.allowedTools.includes(t)
14350
- );
14351
- } else {
14352
- aiConfig.allowedTools = decision.capabilities.allowedTools;
14353
- }
14426
+ aiConfig.allowedTools = _AICheckProvider.intersectAllowedTools(
14427
+ aiConfig.allowedTools,
14428
+ decision.capabilities.allowedTools
14429
+ );
14354
14430
  }
14355
14431
  }
14356
14432
  } catch (err) {
@@ -14471,7 +14547,8 @@ ${preview}`);
14471
14547
  if (cfg.workflow && typeof cfg.workflow === "string") {
14472
14548
  workflowEntriesFromMcp.push({
14473
14549
  workflow: cfg.workflow,
14474
- args: cfg.inputs
14550
+ args: cfg.inputs,
14551
+ name: serverName
14475
14552
  });
14476
14553
  mcpEntriesToRemove.push(serverName);
14477
14554
  logger.debug(
@@ -14612,6 +14689,27 @@ ${preview}`);
14612
14689
  );
14613
14690
  }
14614
14691
  }
14692
+ const allowedToolsJsExpr = config.ai_allowed_tools_js;
14693
+ if (allowedToolsJsExpr && _dependencyResults) {
14694
+ try {
14695
+ const dynamicAllowedTools = this.evaluateAllowedToolsJs(
14696
+ allowedToolsJsExpr,
14697
+ prInfo,
14698
+ _dependencyResults,
14699
+ config
14700
+ );
14701
+ if (dynamicAllowedTools !== null) {
14702
+ aiConfig.allowedTools = dynamicAllowedTools;
14703
+ this.logDebug(
14704
+ `[AI Provider] ai_allowed_tools_js evaluated to: ${JSON.stringify(dynamicAllowedTools)}`
14705
+ );
14706
+ }
14707
+ } catch (error) {
14708
+ logger.error(
14709
+ `[AICheckProvider] Failed to evaluate ai_allowed_tools_js: ${error instanceof Error ? error.message : "Unknown error"}`
14710
+ );
14711
+ }
14712
+ }
14615
14713
  const templateContext = {
14616
14714
  pr: {
14617
14715
  number: prInfo.number,
@@ -15115,6 +15213,65 @@ ${processedPrompt}` : processedPrompt;
15115
15213
  return {};
15116
15214
  }
15117
15215
  }
15216
+ /**
15217
+ * Evaluate ai_allowed_tools_js expression to dynamically compute allowed tools list.
15218
+ * Returns a string array of tool names, or null if the expression returns a non-array.
15219
+ */
15220
+ evaluateAllowedToolsJs(expression, prInfo, dependencyResults, config) {
15221
+ if (!this.sandbox) {
15222
+ this.sandbox = createSecureSandbox();
15223
+ }
15224
+ const outputs = {};
15225
+ for (const [checkId, result] of dependencyResults.entries()) {
15226
+ const summary = result;
15227
+ outputs[checkId] = summary.output !== void 0 ? summary.output : summary;
15228
+ }
15229
+ const jsContext = {
15230
+ outputs,
15231
+ inputs: config.inputs || {},
15232
+ pr: {
15233
+ number: prInfo.number,
15234
+ title: prInfo.title,
15235
+ description: prInfo.body,
15236
+ author: prInfo.author,
15237
+ branch: prInfo.head,
15238
+ base: prInfo.base,
15239
+ authorAssociation: prInfo.authorAssociation
15240
+ },
15241
+ files: prInfo.files?.map((f) => ({
15242
+ filename: f.filename,
15243
+ status: f.status,
15244
+ additions: f.additions,
15245
+ deletions: f.deletions,
15246
+ changes: f.changes
15247
+ })) || [],
15248
+ env: this.buildSafeEnv(),
15249
+ memory: config.__memoryAccessor || {}
15250
+ };
15251
+ try {
15252
+ const result = compileAndRun(this.sandbox, expression, jsContext, {
15253
+ injectLog: true,
15254
+ wrapFunction: true,
15255
+ logPrefix: "[ai_allowed_tools_js]"
15256
+ });
15257
+ if (!Array.isArray(result)) {
15258
+ logger.warn(
15259
+ `[AICheckProvider] ai_allowed_tools_js must return an array, got ${typeof result}`
15260
+ );
15261
+ return null;
15262
+ }
15263
+ const tools = result.filter((item) => typeof item === "string");
15264
+ logger.debug(
15265
+ `[AICheckProvider] ai_allowed_tools_js evaluated to ${tools.length} tools: ${tools.join(", ")}`
15266
+ );
15267
+ return tools;
15268
+ } catch (error) {
15269
+ logger.error(
15270
+ `[AICheckProvider] Failed to evaluate ai_allowed_tools_js: ${error instanceof Error ? error.message : "Unknown error"}`
15271
+ );
15272
+ return null;
15273
+ }
15274
+ }
15118
15275
  /**
15119
15276
  * Build a safe subset of environment variables for sandbox access.
15120
15277
  * Excludes sensitive keys like API keys, secrets, tokens.
@@ -15176,6 +15333,22 @@ ${processedPrompt}` : processedPrompt;
15176
15333
  }
15177
15334
  return tools;
15178
15335
  }
15336
+ /**
15337
+ * Intersect config-level allowedTools with policy-level allowedTools.
15338
+ * When the config list contains glob patterns ("*", "!" exclusions),
15339
+ * it is passed through unchanged — ProbeAgent resolves those patterns.
15340
+ * Literal tool name lists are intersected normally.
15341
+ */
15342
+ static intersectAllowedTools(configTools, policyTools) {
15343
+ if (!configTools) {
15344
+ return policyTools;
15345
+ }
15346
+ const hasGlobs = configTools.some((t) => t === "*" || t.startsWith("!"));
15347
+ if (hasGlobs) {
15348
+ return configTools;
15349
+ }
15350
+ return configTools.filter((t) => policyTools.includes(t));
15351
+ }
15179
15352
  getSupportedConfigKeys() {
15180
15353
  return [
15181
15354
  "type",
@@ -15191,6 +15364,7 @@ ${processedPrompt}` : processedPrompt;
15191
15364
  "ai.mcpServers",
15192
15365
  "ai.enableDelegate",
15193
15366
  "ai.enableTasks",
15367
+ "ai.enableExecutePlan",
15194
15368
  // legacy persona/prompt keys supported in config
15195
15369
  "ai_persona",
15196
15370
  "ai_prompt_type",
@@ -15212,6 +15386,7 @@ ${processedPrompt}` : processedPrompt;
15212
15386
  "ai_custom_tools",
15213
15387
  "ai_custom_tools_js",
15214
15388
  "ai_bash_config_js",
15389
+ "ai_allowed_tools_js",
15215
15390
  "env"
15216
15391
  ];
15217
15392
  }
@@ -39763,6 +39938,20 @@ var init_workflow_check_provider = __esm({
39763
39938
  `[WorkflowProvider] Workflow '${workflow.id}' has null/undefined outputs: [${nullOutputs.join(", ")}]. This may indicate value_js expressions are not finding expected data.`
39764
39939
  );
39765
39940
  }
39941
+ if (!outputs._rawOutput) {
39942
+ const rawParts = [];
39943
+ for (const stepOutput of Object.values(outputsMap)) {
39944
+ if (stepOutput && typeof stepOutput === "object" && typeof stepOutput._rawOutput === "string") {
39945
+ rawParts.push(stepOutput._rawOutput);
39946
+ }
39947
+ }
39948
+ if (rawParts.length > 0) {
39949
+ outputs._rawOutput = rawParts.join("\n\n");
39950
+ logger.debug(
39951
+ `[WorkflowProvider] Propagated _rawOutput from steps (${rawParts.length} blocks, ${outputs._rawOutput.length} chars)`
39952
+ );
39953
+ }
39954
+ }
39766
39955
  return outputs;
39767
39956
  }
39768
39957
  /**
@@ -39909,4 +40098,4 @@ undici/lib/fetch/body.js:
39909
40098
  undici/lib/websocket/frame.js:
39910
40099
  (*! ws. MIT License. Einar Otto Stangvik <einaros@gmail.com> *)
39911
40100
  */
39912
- //# sourceMappingURL=chunk-6ZZ4DPAA.mjs.map
40101
+ //# sourceMappingURL=chunk-5VY5QJTY.mjs.map