@probelabs/visor 0.1.153 → 0.1.154-ee

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 (94) hide show
  1. package/dist/index.js +2023 -88
  2. package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
  3. package/dist/scheduler/schedule-tool.d.ts.map +1 -1
  4. package/dist/sdk/{check-provider-registry-OEPUY5P6.mjs → check-provider-registry-PK3OTEX6.mjs} +7 -7
  5. package/dist/sdk/{check-provider-registry-ZOGNKTC3.mjs → check-provider-registry-PZ6K7G4G.mjs} +7 -7
  6. package/dist/sdk/{chunk-CPYQDJ27.mjs → chunk-AS6LIEO4.mjs} +3 -3
  7. package/dist/sdk/{chunk-Y3XWPKFP.mjs → chunk-GQ7H7E4Y.mjs} +2 -2
  8. package/dist/sdk/{chunk-Y3XWPKFP.mjs.map → chunk-GQ7H7E4Y.mjs.map} +1 -1
  9. package/dist/sdk/{chunk-KBX4OIXL.mjs → chunk-ILIWDV37.mjs} +2 -2
  10. package/dist/sdk/{chunk-U7KB66AN.mjs → chunk-LIRIQICI.mjs} +56 -36
  11. package/dist/sdk/chunk-LIRIQICI.mjs.map +1 -0
  12. package/dist/sdk/{chunk-DNDS7R3N.mjs → chunk-NZADFXHE.mjs} +7 -1
  13. package/dist/sdk/chunk-NZADFXHE.mjs.map +1 -0
  14. package/dist/sdk/{chunk-ZCUGMT7X.mjs → chunk-SPCGI24K.mjs} +3 -3
  15. package/dist/sdk/{chunk-EYQWEVZF.mjs → chunk-WPF7PJ64.mjs} +55 -35
  16. package/dist/sdk/chunk-WPF7PJ64.mjs.map +1 -0
  17. package/dist/sdk/{config-SW3VO4DQ.mjs → config-CWHZO5AL.mjs} +2 -2
  18. package/dist/sdk/{failure-condition-evaluator-R3UE4PE7.mjs → failure-condition-evaluator-LYFZMQ6Y.mjs} +3 -3
  19. package/dist/sdk/{github-frontend-6KZSVSPC.mjs → github-frontend-XKPAYXOT.mjs} +3 -3
  20. package/dist/sdk/{host-A5HS6F6G.mjs → host-6DJCOUJE.mjs} +2 -2
  21. package/dist/sdk/{host-YBJOWFT4.mjs → host-7Y25DDOR.mjs} +2 -2
  22. package/dist/sdk/knex-store-CRORFJE6.mjs +527 -0
  23. package/dist/sdk/knex-store-CRORFJE6.mjs.map +1 -0
  24. package/dist/sdk/loader-NJCF7DUS.mjs +89 -0
  25. package/dist/sdk/loader-NJCF7DUS.mjs.map +1 -0
  26. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
  27. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
  28. package/dist/sdk/{routing-MMEOAH34.mjs → routing-L224WQSY.mjs} +4 -4
  29. package/dist/sdk/{schedule-tool-NMCFABHK.mjs → schedule-tool-HRFONU5J.mjs} +7 -7
  30. package/dist/sdk/{schedule-tool-NYRLSV4F.mjs → schedule-tool-KZ36XTW4.mjs} +7 -7
  31. package/dist/sdk/{schedule-tool-handler-2TFSBZ2O.mjs → schedule-tool-handler-2V4EJEQT.mjs} +7 -7
  32. package/dist/sdk/{schedule-tool-handler-DRVRLVGD.mjs → schedule-tool-handler-KXZC4ZOR.mjs} +7 -7
  33. package/dist/sdk/sdk.js +1677 -277
  34. package/dist/sdk/sdk.js.map +1 -1
  35. package/dist/sdk/sdk.mjs +6 -6
  36. package/dist/sdk/{trace-helpers-JJLVZ2RJ.mjs → trace-helpers-AWTAWKRA.mjs} +2 -2
  37. package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
  38. package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
  39. package/dist/sdk/{workflow-check-provider-GIW4WECT.mjs → workflow-check-provider-HGFTX64I.mjs} +7 -7
  40. package/dist/sdk/{workflow-check-provider-UQMMFLSK.mjs → workflow-check-provider-TXAEY7OU.mjs} +7 -7
  41. package/dist/sdk/{workflow-registry-MHUSKSD6.mjs → workflow-registry-NGV3SESX.mjs} +2 -2
  42. package/dist/slack/schedule-tool-handler.d.ts.map +1 -1
  43. package/dist/workflow-registry.d.ts.map +1 -1
  44. package/package.json +2 -2
  45. package/dist/output/traces/run-2026-03-04T13-24-27-240Z.ndjson +0 -138
  46. package/dist/output/traces/run-2026-03-04T13-25-12-321Z.ndjson +0 -2197
  47. package/dist/sdk/check-provider-registry-CSIZGIKC.mjs +0 -29
  48. package/dist/sdk/chunk-DNDS7R3N.mjs.map +0 -1
  49. package/dist/sdk/chunk-EYQWEVZF.mjs.map +0 -1
  50. package/dist/sdk/chunk-NYK7WDGH.mjs +0 -43754
  51. package/dist/sdk/chunk-NYK7WDGH.mjs.map +0 -1
  52. package/dist/sdk/chunk-SMR5N5MG.mjs +0 -443
  53. package/dist/sdk/chunk-SMR5N5MG.mjs.map +0 -1
  54. package/dist/sdk/chunk-U7KB66AN.mjs.map +0 -1
  55. package/dist/sdk/chunk-VBN45DBR.mjs +0 -1502
  56. package/dist/sdk/chunk-WG7P66MJ.mjs +0 -739
  57. package/dist/sdk/chunk-WG7P66MJ.mjs.map +0 -1
  58. package/dist/sdk/chunk-ZCUGMT7X.mjs.map +0 -1
  59. package/dist/sdk/failure-condition-evaluator-Y32S6DB2.mjs +0 -17
  60. package/dist/sdk/github-frontend-6SIR7QWX.mjs +0 -1368
  61. package/dist/sdk/github-frontend-6SIR7QWX.mjs.map +0 -1
  62. package/dist/sdk/routing-U63OJMZQ.mjs +0 -25
  63. package/dist/sdk/schedule-tool-74VMD77T.mjs +0 -35
  64. package/dist/sdk/schedule-tool-handler-EOQBRZSD.mjs +0 -39
  65. package/dist/sdk/schedule-tool-handler-EOQBRZSD.mjs.map +0 -1
  66. package/dist/sdk/trace-helpers-2BIVADUK.mjs +0 -25
  67. package/dist/sdk/trace-helpers-2BIVADUK.mjs.map +0 -1
  68. package/dist/sdk/trace-helpers-JJLVZ2RJ.mjs.map +0 -1
  69. package/dist/sdk/workflow-check-provider-4NHVFLMQ.mjs +0 -29
  70. package/dist/sdk/workflow-check-provider-4NHVFLMQ.mjs.map +0 -1
  71. package/dist/sdk/workflow-check-provider-GIW4WECT.mjs.map +0 -1
  72. package/dist/sdk/workflow-check-provider-UQMMFLSK.mjs.map +0 -1
  73. package/dist/sdk/workflow-registry-MHUSKSD6.mjs.map +0 -1
  74. package/dist/traces/run-2026-03-04T13-24-27-240Z.ndjson +0 -138
  75. package/dist/traces/run-2026-03-04T13-25-12-321Z.ndjson +0 -2197
  76. /package/dist/sdk/{check-provider-registry-CSIZGIKC.mjs.map → check-provider-registry-PK3OTEX6.mjs.map} +0 -0
  77. /package/dist/sdk/{check-provider-registry-OEPUY5P6.mjs.map → check-provider-registry-PZ6K7G4G.mjs.map} +0 -0
  78. /package/dist/sdk/{chunk-CPYQDJ27.mjs.map → chunk-AS6LIEO4.mjs.map} +0 -0
  79. /package/dist/sdk/{chunk-KBX4OIXL.mjs.map → chunk-ILIWDV37.mjs.map} +0 -0
  80. /package/dist/sdk/{chunk-VBN45DBR.mjs.map → chunk-SPCGI24K.mjs.map} +0 -0
  81. /package/dist/sdk/{check-provider-registry-ZOGNKTC3.mjs.map → config-CWHZO5AL.mjs.map} +0 -0
  82. /package/dist/sdk/{config-SW3VO4DQ.mjs.map → failure-condition-evaluator-LYFZMQ6Y.mjs.map} +0 -0
  83. /package/dist/sdk/{github-frontend-6KZSVSPC.mjs.map → github-frontend-XKPAYXOT.mjs.map} +0 -0
  84. /package/dist/sdk/{host-A5HS6F6G.mjs.map → host-6DJCOUJE.mjs.map} +0 -0
  85. /package/dist/sdk/{host-YBJOWFT4.mjs.map → host-7Y25DDOR.mjs.map} +0 -0
  86. /package/dist/sdk/{failure-condition-evaluator-R3UE4PE7.mjs.map → routing-L224WQSY.mjs.map} +0 -0
  87. /package/dist/sdk/{failure-condition-evaluator-Y32S6DB2.mjs.map → schedule-tool-HRFONU5J.mjs.map} +0 -0
  88. /package/dist/sdk/{routing-MMEOAH34.mjs.map → schedule-tool-KZ36XTW4.mjs.map} +0 -0
  89. /package/dist/sdk/{routing-U63OJMZQ.mjs.map → schedule-tool-handler-2V4EJEQT.mjs.map} +0 -0
  90. /package/dist/sdk/{schedule-tool-74VMD77T.mjs.map → schedule-tool-handler-KXZC4ZOR.mjs.map} +0 -0
  91. /package/dist/sdk/{schedule-tool-NMCFABHK.mjs.map → trace-helpers-AWTAWKRA.mjs.map} +0 -0
  92. /package/dist/sdk/{schedule-tool-NYRLSV4F.mjs.map → workflow-check-provider-HGFTX64I.mjs.map} +0 -0
  93. /package/dist/sdk/{schedule-tool-handler-2TFSBZ2O.mjs.map → workflow-check-provider-TXAEY7OU.mjs.map} +0 -0
  94. /package/dist/sdk/{schedule-tool-handler-DRVRLVGD.mjs.map → workflow-registry-NGV3SESX.mjs.map} +0 -0
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- process.env.VISOR_VERSION = '0.1.153';
3
- process.env.PROBE_VERSION = '0.6.0-rc269';
4
- process.env.VISOR_COMMIT_SHA = '812209528637eae4c9bc2358354377275099850f';
5
- process.env.VISOR_COMMIT_SHORT = '81220952';
2
+ process.env.VISOR_VERSION = '0.1.154';
3
+ process.env.PROBE_VERSION = '0.6.0-rc271';
4
+ process.env.VISOR_COMMIT_SHA = '1ceb9f8073c3ec36e82c277d3e4bfcbf3320ba3b';
5
+ process.env.VISOR_COMMIT_SHORT = '1ceb9f8';
6
6
  /******/ (() => { // webpackBootstrap
7
7
  /******/ var __webpack_modules__ = ({
8
8
 
@@ -161210,7 +161210,7 @@ async function handleDumpPolicyInput(checkId, argv) {
161210
161210
  let PolicyInputBuilder;
161211
161211
  try {
161212
161212
  // @ts-ignore — enterprise/ may not exist in OSS builds (caught at runtime)
161213
- const mod = await Promise.resolve().then(() => __importStar(__nccwpck_require__(71370)));
161213
+ const mod = await Promise.resolve().then(() => __importStar(__nccwpck_require__(17117)));
161214
161214
  PolicyInputBuilder = mod.PolicyInputBuilder;
161215
161215
  }
161216
161216
  catch {
@@ -167084,6 +167084,1810 @@ class DependencyResolver {
167084
167084
  exports.DependencyResolver = DependencyResolver;
167085
167085
 
167086
167086
 
167087
+ /***/ }),
167088
+
167089
+ /***/ 50069:
167090
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
167091
+
167092
+ "use strict";
167093
+
167094
+ /**
167095
+ * Copyright (c) ProbeLabs. All rights reserved.
167096
+ * Licensed under the Elastic License 2.0; you may not use this file except
167097
+ * in compliance with the Elastic License 2.0.
167098
+ */
167099
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
167100
+ if (k2 === undefined) k2 = k;
167101
+ var desc = Object.getOwnPropertyDescriptor(m, k);
167102
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
167103
+ desc = { enumerable: true, get: function() { return m[k]; } };
167104
+ }
167105
+ Object.defineProperty(o, k2, desc);
167106
+ }) : (function(o, m, k, k2) {
167107
+ if (k2 === undefined) k2 = k;
167108
+ o[k2] = m[k];
167109
+ }));
167110
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
167111
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
167112
+ }) : function(o, v) {
167113
+ o["default"] = v;
167114
+ });
167115
+ var __importStar = (this && this.__importStar) || (function () {
167116
+ var ownKeys = function(o) {
167117
+ ownKeys = Object.getOwnPropertyNames || function (o) {
167118
+ var ar = [];
167119
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
167120
+ return ar;
167121
+ };
167122
+ return ownKeys(o);
167123
+ };
167124
+ return function (mod) {
167125
+ if (mod && mod.__esModule) return mod;
167126
+ var result = {};
167127
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
167128
+ __setModuleDefault(result, mod);
167129
+ return result;
167130
+ };
167131
+ })();
167132
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
167133
+ exports.LicenseValidator = void 0;
167134
+ const crypto = __importStar(__nccwpck_require__(76982));
167135
+ const fs = __importStar(__nccwpck_require__(79896));
167136
+ const path = __importStar(__nccwpck_require__(16928));
167137
+ class LicenseValidator {
167138
+ /** Ed25519 public key for license verification (PEM format). */
167139
+ static PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\n' +
167140
+ 'MCowBQYDK2VwAyEAI/Zd08EFmgIdrDm/HXd0l3/5GBt7R1PrdvhdmEXhJlU=\n' +
167141
+ '-----END PUBLIC KEY-----\n';
167142
+ cache = null;
167143
+ static CACHE_TTL = 5 * 60 * 1000; // 5 minutes
167144
+ static GRACE_PERIOD = 72 * 3600 * 1000; // 72 hours after expiry
167145
+ /**
167146
+ * Load and validate license from environment or file.
167147
+ *
167148
+ * Resolution order:
167149
+ * 1. VISOR_LICENSE env var (JWT string)
167150
+ * 2. VISOR_LICENSE_FILE env var (path to file)
167151
+ * 3. .visor-license in project root (cwd)
167152
+ * 4. .visor-license in ~/.config/visor/
167153
+ */
167154
+ async loadAndValidate() {
167155
+ // Return cached result if still fresh
167156
+ if (this.cache && Date.now() - this.cache.validatedAt < LicenseValidator.CACHE_TTL) {
167157
+ return this.cache.payload;
167158
+ }
167159
+ const token = this.resolveToken();
167160
+ if (!token)
167161
+ return null;
167162
+ const payload = this.verifyAndDecode(token);
167163
+ if (!payload)
167164
+ return null;
167165
+ this.cache = { payload, validatedAt: Date.now() };
167166
+ return payload;
167167
+ }
167168
+ /** Check if a specific feature is licensed */
167169
+ hasFeature(feature) {
167170
+ if (!this.cache)
167171
+ return false;
167172
+ return this.cache.payload.features.includes(feature);
167173
+ }
167174
+ /** Check if license is valid (with grace period) */
167175
+ isValid() {
167176
+ if (!this.cache)
167177
+ return false;
167178
+ const now = Date.now();
167179
+ const expiryMs = this.cache.payload.exp * 1000;
167180
+ return now < expiryMs + LicenseValidator.GRACE_PERIOD;
167181
+ }
167182
+ /** Check if the license is within its grace period (expired but still valid) */
167183
+ isInGracePeriod() {
167184
+ if (!this.cache)
167185
+ return false;
167186
+ const now = Date.now();
167187
+ const expiryMs = this.cache.payload.exp * 1000;
167188
+ return now >= expiryMs && now < expiryMs + LicenseValidator.GRACE_PERIOD;
167189
+ }
167190
+ resolveToken() {
167191
+ // 1. Direct env var
167192
+ if (process.env.VISOR_LICENSE) {
167193
+ return process.env.VISOR_LICENSE.trim();
167194
+ }
167195
+ // 2. File path from env (validate against path traversal)
167196
+ if (process.env.VISOR_LICENSE_FILE) {
167197
+ // path.resolve() produces an absolute path with all '..' segments resolved,
167198
+ // so a separate resolved.includes('..') check is unnecessary.
167199
+ const resolved = path.resolve(process.env.VISOR_LICENSE_FILE);
167200
+ const home = process.env.HOME || process.env.USERPROFILE || '';
167201
+ const allowedPrefixes = [path.normalize(process.cwd())];
167202
+ if (home)
167203
+ allowedPrefixes.push(path.normalize(path.join(home, '.config', 'visor')));
167204
+ // Resolve symlinks so an attacker cannot create a symlink inside an
167205
+ // allowed prefix that points to an arbitrary file outside it.
167206
+ let realPath;
167207
+ try {
167208
+ realPath = fs.realpathSync(resolved);
167209
+ }
167210
+ catch {
167211
+ return null; // File doesn't exist or isn't accessible
167212
+ }
167213
+ const isSafe = allowedPrefixes.some(prefix => realPath === prefix || realPath.startsWith(prefix + path.sep));
167214
+ if (!isSafe)
167215
+ return null;
167216
+ return this.readFile(realPath);
167217
+ }
167218
+ // 3. .visor-license in cwd
167219
+ const cwdPath = path.join(process.cwd(), '.visor-license');
167220
+ const cwdToken = this.readFile(cwdPath);
167221
+ if (cwdToken)
167222
+ return cwdToken;
167223
+ // 4. ~/.config/visor/.visor-license
167224
+ const home = process.env.HOME || process.env.USERPROFILE || '';
167225
+ if (home) {
167226
+ const configPath = path.join(home, '.config', 'visor', '.visor-license');
167227
+ const configToken = this.readFile(configPath);
167228
+ if (configToken)
167229
+ return configToken;
167230
+ }
167231
+ return null;
167232
+ }
167233
+ readFile(filePath) {
167234
+ try {
167235
+ return fs.readFileSync(filePath, 'utf-8').trim();
167236
+ }
167237
+ catch {
167238
+ return null;
167239
+ }
167240
+ }
167241
+ verifyAndDecode(token) {
167242
+ try {
167243
+ const parts = token.split('.');
167244
+ if (parts.length !== 3)
167245
+ return null;
167246
+ const [headerB64, payloadB64, signatureB64] = parts;
167247
+ // Decode header to verify algorithm
167248
+ const header = JSON.parse(Buffer.from(headerB64, 'base64url').toString());
167249
+ if (header.alg !== 'EdDSA')
167250
+ return null;
167251
+ // Verify signature
167252
+ const data = `${headerB64}.${payloadB64}`;
167253
+ const signature = Buffer.from(signatureB64, 'base64url');
167254
+ const publicKey = crypto.createPublicKey(LicenseValidator.PUBLIC_KEY);
167255
+ // Validate that the loaded public key is actually Ed25519 (OID 1.3.101.112).
167256
+ // This prevents algorithm-confusion attacks if the embedded key were ever
167257
+ // swapped to a different type.
167258
+ if (publicKey.asymmetricKeyType !== 'ed25519') {
167259
+ return null;
167260
+ }
167261
+ // Ed25519 verification: algorithm must be null because EdDSA performs its
167262
+ // own internal hashing (SHA-512) — passing a digest algorithm here would
167263
+ // cause Node.js to throw. The key type is validated above.
167264
+ const isValid = crypto.verify(null, Buffer.from(data), publicKey, signature);
167265
+ if (!isValid)
167266
+ return null;
167267
+ // Decode payload
167268
+ const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString());
167269
+ // Validate required fields
167270
+ if (!payload.org ||
167271
+ !Array.isArray(payload.features) ||
167272
+ typeof payload.exp !== 'number' ||
167273
+ typeof payload.iat !== 'number' ||
167274
+ !payload.sub) {
167275
+ return null;
167276
+ }
167277
+ // Check expiry (with grace period)
167278
+ const now = Date.now();
167279
+ const expiryMs = payload.exp * 1000;
167280
+ if (now >= expiryMs + LicenseValidator.GRACE_PERIOD) {
167281
+ return null;
167282
+ }
167283
+ return payload;
167284
+ }
167285
+ catch {
167286
+ return null;
167287
+ }
167288
+ }
167289
+ }
167290
+ exports.LicenseValidator = LicenseValidator;
167291
+
167292
+
167293
+ /***/ }),
167294
+
167295
+ /***/ 87068:
167296
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
167297
+
167298
+ "use strict";
167299
+
167300
+ /**
167301
+ * Copyright (c) ProbeLabs. All rights reserved.
167302
+ * Licensed under the Elastic License 2.0; you may not use this file except
167303
+ * in compliance with the Elastic License 2.0.
167304
+ */
167305
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
167306
+ if (k2 === undefined) k2 = k;
167307
+ var desc = Object.getOwnPropertyDescriptor(m, k);
167308
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
167309
+ desc = { enumerable: true, get: function() { return m[k]; } };
167310
+ }
167311
+ Object.defineProperty(o, k2, desc);
167312
+ }) : (function(o, m, k, k2) {
167313
+ if (k2 === undefined) k2 = k;
167314
+ o[k2] = m[k];
167315
+ }));
167316
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
167317
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
167318
+ }) : function(o, v) {
167319
+ o["default"] = v;
167320
+ });
167321
+ var __importStar = (this && this.__importStar) || (function () {
167322
+ var ownKeys = function(o) {
167323
+ ownKeys = Object.getOwnPropertyNames || function (o) {
167324
+ var ar = [];
167325
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
167326
+ return ar;
167327
+ };
167328
+ return ownKeys(o);
167329
+ };
167330
+ return function (mod) {
167331
+ if (mod && mod.__esModule) return mod;
167332
+ var result = {};
167333
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
167334
+ __setModuleDefault(result, mod);
167335
+ return result;
167336
+ };
167337
+ })();
167338
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
167339
+ exports.loadEnterprisePolicyEngine = loadEnterprisePolicyEngine;
167340
+ exports.loadEnterpriseStoreBackend = loadEnterpriseStoreBackend;
167341
+ const default_engine_1 = __nccwpck_require__(93866);
167342
+ /**
167343
+ * Load the enterprise policy engine if licensed, otherwise return the default no-op engine.
167344
+ *
167345
+ * This is the sole import boundary between OSS and enterprise code. Core code
167346
+ * must only import from this module (via dynamic `await import()`), never from
167347
+ * individual enterprise submodules.
167348
+ */
167349
+ async function loadEnterprisePolicyEngine(config) {
167350
+ try {
167351
+ const { LicenseValidator } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(50069)));
167352
+ const validator = new LicenseValidator();
167353
+ const license = await validator.loadAndValidate();
167354
+ if (!license || !validator.hasFeature('policy')) {
167355
+ return new default_engine_1.DefaultPolicyEngine();
167356
+ }
167357
+ if (validator.isInGracePeriod()) {
167358
+ // eslint-disable-next-line no-console
167359
+ console.warn('[visor:enterprise] License has expired but is within the 72-hour grace period. ' +
167360
+ 'Please renew your license.');
167361
+ }
167362
+ const { OpaPolicyEngine } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(39530)));
167363
+ const engine = new OpaPolicyEngine(config);
167364
+ await engine.initialize(config);
167365
+ return engine;
167366
+ }
167367
+ catch (err) {
167368
+ // Enterprise code not available or initialization failed
167369
+ const msg = err instanceof Error ? err.message : String(err);
167370
+ try {
167371
+ const { logger } = __nccwpck_require__(86999);
167372
+ logger.warn(`[PolicyEngine] Enterprise policy init failed, falling back to default: ${msg}`);
167373
+ }
167374
+ catch {
167375
+ // silent
167376
+ }
167377
+ return new default_engine_1.DefaultPolicyEngine();
167378
+ }
167379
+ }
167380
+ /**
167381
+ * Load the enterprise schedule store backend if licensed.
167382
+ *
167383
+ * @param driver Database driver ('postgresql', 'mysql', or 'mssql')
167384
+ * @param storageConfig Storage configuration with connection details
167385
+ * @param haConfig Optional HA configuration
167386
+ * @throws Error if enterprise license is not available or missing 'scheduler-sql' feature
167387
+ */
167388
+ async function loadEnterpriseStoreBackend(driver, storageConfig, haConfig) {
167389
+ const { LicenseValidator } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(50069)));
167390
+ const validator = new LicenseValidator();
167391
+ const license = await validator.loadAndValidate();
167392
+ if (!license || !validator.hasFeature('scheduler-sql')) {
167393
+ throw new Error(`The ${driver} schedule storage driver requires a Visor Enterprise license ` +
167394
+ `with the 'scheduler-sql' feature. Please upgrade or use driver: 'sqlite' (default).`);
167395
+ }
167396
+ if (validator.isInGracePeriod()) {
167397
+ // eslint-disable-next-line no-console
167398
+ console.warn('[visor:enterprise] License has expired but is within the 72-hour grace period. ' +
167399
+ 'Please renew your license.');
167400
+ }
167401
+ const { KnexStoreBackend } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(63737)));
167402
+ return new KnexStoreBackend(driver, storageConfig, haConfig);
167403
+ }
167404
+
167405
+
167406
+ /***/ }),
167407
+
167408
+ /***/ 628:
167409
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
167410
+
167411
+ "use strict";
167412
+
167413
+ /**
167414
+ * Copyright (c) ProbeLabs. All rights reserved.
167415
+ * Licensed under the Elastic License 2.0; you may not use this file except
167416
+ * in compliance with the Elastic License 2.0.
167417
+ */
167418
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
167419
+ if (k2 === undefined) k2 = k;
167420
+ var desc = Object.getOwnPropertyDescriptor(m, k);
167421
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
167422
+ desc = { enumerable: true, get: function() { return m[k]; } };
167423
+ }
167424
+ Object.defineProperty(o, k2, desc);
167425
+ }) : (function(o, m, k, k2) {
167426
+ if (k2 === undefined) k2 = k;
167427
+ o[k2] = m[k];
167428
+ }));
167429
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
167430
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
167431
+ }) : function(o, v) {
167432
+ o["default"] = v;
167433
+ });
167434
+ var __importStar = (this && this.__importStar) || (function () {
167435
+ var ownKeys = function(o) {
167436
+ ownKeys = Object.getOwnPropertyNames || function (o) {
167437
+ var ar = [];
167438
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
167439
+ return ar;
167440
+ };
167441
+ return ownKeys(o);
167442
+ };
167443
+ return function (mod) {
167444
+ if (mod && mod.__esModule) return mod;
167445
+ var result = {};
167446
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
167447
+ __setModuleDefault(result, mod);
167448
+ return result;
167449
+ };
167450
+ })();
167451
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
167452
+ exports.OpaCompiler = void 0;
167453
+ const fs = __importStar(__nccwpck_require__(79896));
167454
+ const path = __importStar(__nccwpck_require__(16928));
167455
+ const os = __importStar(__nccwpck_require__(70857));
167456
+ const crypto = __importStar(__nccwpck_require__(76982));
167457
+ const child_process_1 = __nccwpck_require__(35317);
167458
+ /**
167459
+ * OPA Rego Compiler - compiles .rego policy files to WASM bundles using the `opa` CLI.
167460
+ *
167461
+ * Handles:
167462
+ * - Resolving input paths to WASM bytes (direct .wasm, directory with policy.wasm, or .rego files)
167463
+ * - Compiling .rego files to WASM via `opa build`
167464
+ * - Caching compiled bundles based on content hashes
167465
+ * - Extracting policy.wasm from OPA tar.gz bundles
167466
+ *
167467
+ * Requires:
167468
+ * - `opa` CLI on PATH (only when auto-compiling .rego files)
167469
+ */
167470
+ class OpaCompiler {
167471
+ static CACHE_DIR = path.join(os.tmpdir(), 'visor-opa-cache');
167472
+ /**
167473
+ * Resolve the input paths to WASM bytes.
167474
+ *
167475
+ * Strategy:
167476
+ * 1. If any path is a .wasm file, read it directly
167477
+ * 2. If a directory contains policy.wasm, read it
167478
+ * 3. Otherwise, collect all .rego files and auto-compile via `opa build`
167479
+ */
167480
+ async resolveWasmBytes(paths) {
167481
+ // Collect .rego files and check for existing .wasm
167482
+ const regoFiles = [];
167483
+ for (const p of paths) {
167484
+ const resolved = path.resolve(p);
167485
+ // Reject paths containing '..' after resolution (path traversal)
167486
+ if (path.normalize(resolved).includes('..')) {
167487
+ throw new Error(`Policy path contains traversal sequences: ${p}`);
167488
+ }
167489
+ // Direct .wasm file
167490
+ if (resolved.endsWith('.wasm') && fs.existsSync(resolved)) {
167491
+ return fs.readFileSync(resolved);
167492
+ }
167493
+ if (!fs.existsSync(resolved))
167494
+ continue;
167495
+ const stat = fs.statSync(resolved);
167496
+ if (stat.isDirectory()) {
167497
+ // Check for pre-compiled policy.wasm in directory
167498
+ const wasmCandidate = path.join(resolved, 'policy.wasm');
167499
+ if (fs.existsSync(wasmCandidate)) {
167500
+ return fs.readFileSync(wasmCandidate);
167501
+ }
167502
+ // Collect all .rego files from directory
167503
+ const files = fs.readdirSync(resolved);
167504
+ for (const f of files) {
167505
+ if (f.endsWith('.rego')) {
167506
+ regoFiles.push(path.join(resolved, f));
167507
+ }
167508
+ }
167509
+ }
167510
+ else if (resolved.endsWith('.rego')) {
167511
+ regoFiles.push(resolved);
167512
+ }
167513
+ }
167514
+ if (regoFiles.length === 0) {
167515
+ throw new Error(`OPA WASM evaluator: no .wasm bundle or .rego files found in: ${paths.join(', ')}`);
167516
+ }
167517
+ // Auto-compile .rego -> .wasm
167518
+ return this.compileRego(regoFiles);
167519
+ }
167520
+ /**
167521
+ * Auto-compile .rego files to a WASM bundle using the `opa` CLI.
167522
+ *
167523
+ * Caches the compiled bundle based on a content hash of all input .rego files
167524
+ * so subsequent runs skip compilation if policies haven't changed.
167525
+ */
167526
+ compileRego(regoFiles) {
167527
+ // Check that `opa` CLI is available
167528
+ try {
167529
+ (0, child_process_1.execFileSync)('opa', ['version'], { stdio: 'pipe' });
167530
+ }
167531
+ catch {
167532
+ throw new Error('OPA CLI (`opa`) not found on PATH. Install it from https://www.openpolicyagent.org/docs/latest/#running-opa\n' +
167533
+ 'Or pre-compile your .rego files: opa build -t wasm -e visor -o bundle.tar.gz ' +
167534
+ regoFiles.join(' '));
167535
+ }
167536
+ // Compute content hash for cache key
167537
+ const hash = crypto.createHash('sha256');
167538
+ for (const f of regoFiles.sort()) {
167539
+ hash.update(fs.readFileSync(f));
167540
+ hash.update(f); // include filename for disambiguation
167541
+ }
167542
+ const cacheKey = hash.digest('hex').slice(0, 16);
167543
+ const cacheDir = OpaCompiler.CACHE_DIR;
167544
+ const cachedWasm = path.join(cacheDir, `${cacheKey}.wasm`);
167545
+ // Return cached bundle if still valid
167546
+ if (fs.existsSync(cachedWasm)) {
167547
+ return fs.readFileSync(cachedWasm);
167548
+ }
167549
+ // Compile to WASM via opa build
167550
+ fs.mkdirSync(cacheDir, { recursive: true });
167551
+ const bundleTar = path.join(cacheDir, `${cacheKey}-bundle.tar.gz`);
167552
+ try {
167553
+ const args = [
167554
+ 'build',
167555
+ '-t',
167556
+ 'wasm',
167557
+ '-e',
167558
+ 'visor', // entrypoint: the visor package tree
167559
+ '-o',
167560
+ bundleTar,
167561
+ ...regoFiles,
167562
+ ];
167563
+ (0, child_process_1.execFileSync)('opa', args, {
167564
+ stdio: 'pipe',
167565
+ timeout: 30000,
167566
+ });
167567
+ }
167568
+ catch (err) {
167569
+ const stderr = err?.stderr?.toString() || '';
167570
+ throw new Error(`Failed to compile .rego files to WASM:\n${stderr}\n` +
167571
+ 'Ensure your .rego files are valid and the `opa` CLI is installed.');
167572
+ }
167573
+ // Extract policy.wasm from the tar.gz bundle
167574
+ // OPA bundles are tar.gz with /policy.wasm inside
167575
+ try {
167576
+ (0, child_process_1.execFileSync)('tar', ['-xzf', bundleTar, '-C', cacheDir, '/policy.wasm'], {
167577
+ stdio: 'pipe',
167578
+ });
167579
+ const extractedWasm = path.join(cacheDir, 'policy.wasm');
167580
+ if (fs.existsSync(extractedWasm)) {
167581
+ // Move to cache-key named file
167582
+ fs.renameSync(extractedWasm, cachedWasm);
167583
+ }
167584
+ }
167585
+ catch {
167586
+ // Some tar implementations don't like leading /
167587
+ try {
167588
+ (0, child_process_1.execFileSync)('tar', ['-xzf', bundleTar, '-C', cacheDir, 'policy.wasm'], {
167589
+ stdio: 'pipe',
167590
+ });
167591
+ const extractedWasm = path.join(cacheDir, 'policy.wasm');
167592
+ if (fs.existsSync(extractedWasm)) {
167593
+ fs.renameSync(extractedWasm, cachedWasm);
167594
+ }
167595
+ }
167596
+ catch (err2) {
167597
+ throw new Error(`Failed to extract policy.wasm from OPA bundle: ${err2?.message || err2}`);
167598
+ }
167599
+ }
167600
+ // Clean up tar
167601
+ try {
167602
+ fs.unlinkSync(bundleTar);
167603
+ }
167604
+ catch { }
167605
+ if (!fs.existsSync(cachedWasm)) {
167606
+ throw new Error('OPA build succeeded but policy.wasm was not found in the bundle');
167607
+ }
167608
+ return fs.readFileSync(cachedWasm);
167609
+ }
167610
+ }
167611
+ exports.OpaCompiler = OpaCompiler;
167612
+
167613
+
167614
+ /***/ }),
167615
+
167616
+ /***/ 44693:
167617
+ /***/ ((__unused_webpack_module, exports) => {
167618
+
167619
+ "use strict";
167620
+
167621
+ /**
167622
+ * Copyright (c) ProbeLabs. All rights reserved.
167623
+ * Licensed under the Elastic License 2.0; you may not use this file except
167624
+ * in compliance with the Elastic License 2.0.
167625
+ */
167626
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
167627
+ exports.OpaHttpEvaluator = void 0;
167628
+ /**
167629
+ * OPA HTTP Evaluator - evaluates policies via an external OPA server's REST API.
167630
+ *
167631
+ * Uses the built-in `fetch` API (Node 18+), so no extra dependencies are needed.
167632
+ */
167633
+ class OpaHttpEvaluator {
167634
+ baseUrl;
167635
+ timeout;
167636
+ constructor(baseUrl, timeout = 5000) {
167637
+ // Validate URL format and protocol
167638
+ let parsed;
167639
+ try {
167640
+ parsed = new URL(baseUrl);
167641
+ }
167642
+ catch {
167643
+ throw new Error(`OPA HTTP evaluator: invalid URL: ${baseUrl}`);
167644
+ }
167645
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
167646
+ throw new Error(`OPA HTTP evaluator: url must use http:// or https:// protocol, got: ${baseUrl}`);
167647
+ }
167648
+ // Block cloud metadata, loopback, link-local, and private network addresses
167649
+ const hostname = parsed.hostname;
167650
+ if (this.isBlockedHostname(hostname)) {
167651
+ throw new Error(`OPA HTTP evaluator: url must not point to internal, loopback, or private network addresses`);
167652
+ }
167653
+ // Normalize: strip trailing slash
167654
+ this.baseUrl = baseUrl.replace(/\/+$/, '');
167655
+ this.timeout = timeout;
167656
+ }
167657
+ /**
167658
+ * Check if a hostname is blocked due to SSRF concerns.
167659
+ *
167660
+ * Blocks:
167661
+ * - Loopback addresses (127.x.x.x, localhost, 0.0.0.0, ::1)
167662
+ * - Link-local addresses (169.254.x.x)
167663
+ * - Private networks (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
167664
+ * - IPv6 unique local addresses (fd00::/8)
167665
+ * - Cloud metadata services (*.internal)
167666
+ */
167667
+ isBlockedHostname(hostname) {
167668
+ if (!hostname)
167669
+ return true; // block empty hostnames
167670
+ // Normalize hostname: lowercase and remove brackets for IPv6
167671
+ const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, '');
167672
+ // Block .internal domains (cloud metadata services)
167673
+ if (normalized === 'metadata.google.internal' || normalized.endsWith('.internal')) {
167674
+ return true;
167675
+ }
167676
+ // Block localhost variants
167677
+ if (normalized === 'localhost' || normalized === 'localhost.localdomain') {
167678
+ return true;
167679
+ }
167680
+ // Block IPv6 loopback
167681
+ if (normalized === '::1' || normalized === '0:0:0:0:0:0:0:1') {
167682
+ return true;
167683
+ }
167684
+ // Check IPv4 patterns
167685
+ const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
167686
+ const ipv4Match = normalized.match(ipv4Pattern);
167687
+ if (ipv4Match) {
167688
+ const octets = ipv4Match.slice(1, 5).map(Number);
167689
+ // Validate octets are in range [0, 255]
167690
+ if (octets.some(octet => octet > 255)) {
167691
+ return false;
167692
+ }
167693
+ const [a, b] = octets;
167694
+ // Block loopback: 127.0.0.0/8
167695
+ if (a === 127) {
167696
+ return true;
167697
+ }
167698
+ // Block 0.0.0.0/8 (this host)
167699
+ if (a === 0) {
167700
+ return true;
167701
+ }
167702
+ // Block link-local: 169.254.0.0/16
167703
+ if (a === 169 && b === 254) {
167704
+ return true;
167705
+ }
167706
+ // Block private networks
167707
+ // 10.0.0.0/8
167708
+ if (a === 10) {
167709
+ return true;
167710
+ }
167711
+ // 172.16.0.0/12 (172.16.x.x through 172.31.x.x)
167712
+ if (a === 172 && b >= 16 && b <= 31) {
167713
+ return true;
167714
+ }
167715
+ // 192.168.0.0/16
167716
+ if (a === 192 && b === 168) {
167717
+ return true;
167718
+ }
167719
+ }
167720
+ // Check IPv6 patterns
167721
+ // Block unique local addresses: fd00::/8
167722
+ if (normalized.startsWith('fd') || normalized.startsWith('fc')) {
167723
+ return true;
167724
+ }
167725
+ // Block link-local: fe80::/10
167726
+ if (normalized.startsWith('fe80:')) {
167727
+ return true;
167728
+ }
167729
+ return false;
167730
+ }
167731
+ /**
167732
+ * Evaluate a policy rule against an input document via OPA REST API.
167733
+ *
167734
+ * @param input - The input document to evaluate
167735
+ * @param rulePath - OPA rule path (e.g., 'visor/check/execute')
167736
+ * @returns The result object from OPA, or undefined on error
167737
+ */
167738
+ async evaluate(input, rulePath) {
167739
+ // OPA Data API: POST /v1/data/<path>
167740
+ const encodedPath = rulePath
167741
+ .split('/')
167742
+ .map(s => encodeURIComponent(s))
167743
+ .join('/');
167744
+ const url = `${this.baseUrl}/v1/data/${encodedPath}`;
167745
+ const controller = new AbortController();
167746
+ const timer = setTimeout(() => controller.abort(), this.timeout);
167747
+ try {
167748
+ const response = await fetch(url, {
167749
+ method: 'POST',
167750
+ headers: { 'Content-Type': 'application/json' },
167751
+ body: JSON.stringify({ input }),
167752
+ signal: controller.signal,
167753
+ });
167754
+ if (!response.ok) {
167755
+ throw new Error(`OPA HTTP ${response.status}: ${response.statusText}`);
167756
+ }
167757
+ let body;
167758
+ try {
167759
+ body = await response.json();
167760
+ }
167761
+ catch (jsonErr) {
167762
+ throw new Error(`OPA HTTP evaluator: failed to parse JSON response: ${jsonErr instanceof Error ? jsonErr.message : String(jsonErr)}`);
167763
+ }
167764
+ // OPA returns { result: { ... } }
167765
+ return body?.result;
167766
+ }
167767
+ finally {
167768
+ clearTimeout(timer);
167769
+ }
167770
+ }
167771
+ async shutdown() {
167772
+ // No persistent connections to close
167773
+ }
167774
+ }
167775
+ exports.OpaHttpEvaluator = OpaHttpEvaluator;
167776
+
167777
+
167778
+ /***/ }),
167779
+
167780
+ /***/ 39530:
167781
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
167782
+
167783
+ "use strict";
167784
+
167785
+ /**
167786
+ * Copyright (c) ProbeLabs. All rights reserved.
167787
+ * Licensed under the Elastic License 2.0; you may not use this file except
167788
+ * in compliance with the Elastic License 2.0.
167789
+ */
167790
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
167791
+ exports.OpaPolicyEngine = void 0;
167792
+ const opa_wasm_evaluator_1 = __nccwpck_require__(8613);
167793
+ const opa_http_evaluator_1 = __nccwpck_require__(44693);
167794
+ const policy_input_builder_1 = __nccwpck_require__(17117);
167795
+ /**
167796
+ * Enterprise OPA Policy Engine.
167797
+ *
167798
+ * Wraps both WASM (local) and HTTP (remote) OPA evaluators behind the
167799
+ * OSS PolicyEngine interface. All OPA input building and role resolution
167800
+ * is handled internally — the OSS call sites pass only plain types.
167801
+ */
167802
+ class OpaPolicyEngine {
167803
+ evaluator = null;
167804
+ fallback;
167805
+ timeout;
167806
+ config;
167807
+ inputBuilder = null;
167808
+ logger = null;
167809
+ constructor(config) {
167810
+ this.config = config;
167811
+ this.fallback = config.fallback || 'deny';
167812
+ this.timeout = config.timeout || 5000;
167813
+ }
167814
+ async initialize(config) {
167815
+ // Resolve logger once at initialization
167816
+ try {
167817
+ this.logger = (__nccwpck_require__(86999).logger);
167818
+ }
167819
+ catch {
167820
+ // logger not available in this context
167821
+ }
167822
+ // Build actor/repo context from environment (available at engine init time)
167823
+ const actor = {
167824
+ authorAssociation: process.env.VISOR_AUTHOR_ASSOCIATION,
167825
+ login: process.env.VISOR_AUTHOR_LOGIN || process.env.GITHUB_ACTOR,
167826
+ isLocalMode: !process.env.GITHUB_ACTIONS,
167827
+ };
167828
+ const repo = {
167829
+ owner: process.env.GITHUB_REPOSITORY_OWNER,
167830
+ name: process.env.GITHUB_REPOSITORY?.split('/')[1],
167831
+ branch: process.env.GITHUB_HEAD_REF,
167832
+ baseBranch: process.env.GITHUB_BASE_REF,
167833
+ event: process.env.GITHUB_EVENT_NAME,
167834
+ };
167835
+ const prNum = process.env.GITHUB_PR_NUMBER
167836
+ ? parseInt(process.env.GITHUB_PR_NUMBER, 10)
167837
+ : undefined;
167838
+ const pullRequest = {
167839
+ number: prNum !== undefined && Number.isFinite(prNum) ? prNum : undefined,
167840
+ };
167841
+ this.inputBuilder = new policy_input_builder_1.PolicyInputBuilder(config, actor, repo, pullRequest);
167842
+ if (config.engine === 'local') {
167843
+ if (!config.rules) {
167844
+ throw new Error('OPA local mode requires `policy.rules` path to .wasm or .rego files');
167845
+ }
167846
+ const wasm = new opa_wasm_evaluator_1.OpaWasmEvaluator();
167847
+ await wasm.initialize(config.rules);
167848
+ if (config.data) {
167849
+ wasm.loadData(config.data);
167850
+ }
167851
+ this.evaluator = wasm;
167852
+ }
167853
+ else if (config.engine === 'remote') {
167854
+ if (!config.url) {
167855
+ throw new Error('OPA remote mode requires `policy.url` pointing to OPA server');
167856
+ }
167857
+ this.evaluator = new opa_http_evaluator_1.OpaHttpEvaluator(config.url, this.timeout);
167858
+ }
167859
+ else {
167860
+ this.evaluator = null;
167861
+ }
167862
+ }
167863
+ /**
167864
+ * Update actor/repo/PR context (e.g., after PR info becomes available).
167865
+ * Called by the enterprise loader when engine context is enriched.
167866
+ */
167867
+ setActorContext(actor, repo, pullRequest) {
167868
+ this.inputBuilder = new policy_input_builder_1.PolicyInputBuilder(this.config, actor, repo, pullRequest);
167869
+ }
167870
+ async evaluateCheckExecution(checkId, checkConfig) {
167871
+ if (!this.evaluator || !this.inputBuilder)
167872
+ return { allowed: true };
167873
+ const cfg = checkConfig && typeof checkConfig === 'object'
167874
+ ? checkConfig
167875
+ : {};
167876
+ const policyOverride = cfg.policy;
167877
+ const input = this.inputBuilder.forCheckExecution({
167878
+ id: checkId,
167879
+ type: cfg.type || 'ai',
167880
+ group: cfg.group,
167881
+ tags: cfg.tags,
167882
+ criticality: cfg.criticality,
167883
+ sandbox: cfg.sandbox,
167884
+ policy: policyOverride,
167885
+ });
167886
+ return this.doEvaluate(input, this.resolveRulePath('check.execute', policyOverride?.rule));
167887
+ }
167888
+ async evaluateToolInvocation(serverName, methodName, transport) {
167889
+ if (!this.evaluator || !this.inputBuilder)
167890
+ return { allowed: true };
167891
+ const input = this.inputBuilder.forToolInvocation(serverName, methodName, transport);
167892
+ return this.doEvaluate(input, 'visor/tool/invoke');
167893
+ }
167894
+ async evaluateCapabilities(checkId, capabilities) {
167895
+ if (!this.evaluator || !this.inputBuilder)
167896
+ return { allowed: true };
167897
+ const input = this.inputBuilder.forCapabilityResolve(checkId, capabilities);
167898
+ return this.doEvaluate(input, 'visor/capability/resolve');
167899
+ }
167900
+ async shutdown() {
167901
+ if (this.evaluator && 'shutdown' in this.evaluator) {
167902
+ await this.evaluator.shutdown();
167903
+ }
167904
+ this.evaluator = null;
167905
+ this.inputBuilder = null;
167906
+ }
167907
+ resolveRulePath(defaultScope, override) {
167908
+ if (override) {
167909
+ return override.startsWith('visor/') ? override : `visor/${override}`;
167910
+ }
167911
+ return `visor/${defaultScope.replace(/\./g, '/')}`;
167912
+ }
167913
+ async doEvaluate(input, rulePath) {
167914
+ try {
167915
+ this.logger?.debug(`[PolicyEngine] Evaluating ${rulePath}`, JSON.stringify(input));
167916
+ let timer;
167917
+ const timeoutPromise = new Promise((_resolve, reject) => {
167918
+ timer = setTimeout(() => reject(new Error('policy evaluation timeout')), this.timeout);
167919
+ });
167920
+ try {
167921
+ const result = await Promise.race([this.rawEvaluate(input, rulePath), timeoutPromise]);
167922
+ const decision = this.parseDecision(result);
167923
+ // In warn mode, override denied decisions to allowed but flag as warn
167924
+ if (!decision.allowed && this.fallback === 'warn') {
167925
+ decision.allowed = true;
167926
+ decision.warn = true;
167927
+ decision.reason = `audit: ${decision.reason || 'policy denied'}`;
167928
+ }
167929
+ this.logger?.debug(`[PolicyEngine] Decision for ${rulePath}: allowed=${decision.allowed}, warn=${decision.warn || false}, reason=${decision.reason || 'none'}`);
167930
+ return decision;
167931
+ }
167932
+ finally {
167933
+ if (timer)
167934
+ clearTimeout(timer);
167935
+ }
167936
+ }
167937
+ catch (err) {
167938
+ const msg = err instanceof Error ? err.message : String(err);
167939
+ this.logger?.warn(`[PolicyEngine] Evaluation failed for ${rulePath}: ${msg}`);
167940
+ return {
167941
+ allowed: this.fallback === 'allow' || this.fallback === 'warn',
167942
+ warn: this.fallback === 'warn' ? true : undefined,
167943
+ reason: `policy evaluation failed, fallback=${this.fallback}`,
167944
+ };
167945
+ }
167946
+ }
167947
+ async rawEvaluate(input, rulePath) {
167948
+ if (this.evaluator instanceof opa_wasm_evaluator_1.OpaWasmEvaluator) {
167949
+ const result = await this.evaluator.evaluate(input);
167950
+ // WASM compiled with `-e visor` entrypoint returns the full visor package tree.
167951
+ // Navigate to the specific rule subtree using rulePath segments.
167952
+ // e.g., 'visor/check/execute' → result.check.execute
167953
+ return this.navigateWasmResult(result, rulePath);
167954
+ }
167955
+ return this.evaluator.evaluate(input, rulePath);
167956
+ }
167957
+ /**
167958
+ * Navigate nested OPA WASM result tree to reach the specific rule's output.
167959
+ * The WASM entrypoint `-e visor` means the result root IS the visor package,
167960
+ * so we strip the `visor/` prefix and walk the remaining segments.
167961
+ */
167962
+ navigateWasmResult(result, rulePath) {
167963
+ if (!result || typeof result !== 'object')
167964
+ return result;
167965
+ // Strip the 'visor/' prefix (matches our compilation entrypoint)
167966
+ const segments = rulePath.replace(/^visor\//, '').split('/');
167967
+ let current = result;
167968
+ for (const seg of segments) {
167969
+ if (current && typeof current === 'object' && seg in current) {
167970
+ current = current[seg];
167971
+ }
167972
+ else {
167973
+ return undefined; // path not found in result tree
167974
+ }
167975
+ }
167976
+ return current;
167977
+ }
167978
+ parseDecision(result) {
167979
+ if (result === undefined || result === null) {
167980
+ return {
167981
+ allowed: this.fallback === 'allow' || this.fallback === 'warn',
167982
+ warn: this.fallback === 'warn' ? true : undefined,
167983
+ reason: this.fallback === 'warn' ? 'audit: no policy result' : 'no policy result',
167984
+ };
167985
+ }
167986
+ const allowed = result.allowed !== false;
167987
+ const decision = {
167988
+ allowed,
167989
+ reason: result.reason,
167990
+ };
167991
+ if (result.capabilities) {
167992
+ decision.capabilities = result.capabilities;
167993
+ }
167994
+ return decision;
167995
+ }
167996
+ }
167997
+ exports.OpaPolicyEngine = OpaPolicyEngine;
167998
+
167999
+
168000
+ /***/ }),
168001
+
168002
+ /***/ 8613:
168003
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
168004
+
168005
+ "use strict";
168006
+
168007
+ /**
168008
+ * Copyright (c) ProbeLabs. All rights reserved.
168009
+ * Licensed under the Elastic License 2.0; you may not use this file except
168010
+ * in compliance with the Elastic License 2.0.
168011
+ */
168012
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
168013
+ if (k2 === undefined) k2 = k;
168014
+ var desc = Object.getOwnPropertyDescriptor(m, k);
168015
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
168016
+ desc = { enumerable: true, get: function() { return m[k]; } };
168017
+ }
168018
+ Object.defineProperty(o, k2, desc);
168019
+ }) : (function(o, m, k, k2) {
168020
+ if (k2 === undefined) k2 = k;
168021
+ o[k2] = m[k];
168022
+ }));
168023
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
168024
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
168025
+ }) : function(o, v) {
168026
+ o["default"] = v;
168027
+ });
168028
+ var __importStar = (this && this.__importStar) || (function () {
168029
+ var ownKeys = function(o) {
168030
+ ownKeys = Object.getOwnPropertyNames || function (o) {
168031
+ var ar = [];
168032
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
168033
+ return ar;
168034
+ };
168035
+ return ownKeys(o);
168036
+ };
168037
+ return function (mod) {
168038
+ if (mod && mod.__esModule) return mod;
168039
+ var result = {};
168040
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
168041
+ __setModuleDefault(result, mod);
168042
+ return result;
168043
+ };
168044
+ })();
168045
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
168046
+ exports.OpaWasmEvaluator = void 0;
168047
+ const fs = __importStar(__nccwpck_require__(79896));
168048
+ const path = __importStar(__nccwpck_require__(16928));
168049
+ const opa_compiler_1 = __nccwpck_require__(628);
168050
+ /**
168051
+ * OPA WASM Evaluator - loads and evaluates OPA policies locally.
168052
+ *
168053
+ * Supports three input formats:
168054
+ * 1. Pre-compiled `.wasm` bundle — loaded directly (fastest startup)
168055
+ * 2. `.rego` files or directory — auto-compiled to WASM via `opa build` CLI
168056
+ * 3. Directory with `policy.wasm` inside — loaded directly
168057
+ *
168058
+ * Compilation and caching of .rego files is delegated to {@link OpaCompiler}.
168059
+ *
168060
+ * Requires:
168061
+ * - `@open-policy-agent/opa-wasm` npm package (optional dep)
168062
+ * - `opa` CLI on PATH (only when auto-compiling .rego files)
168063
+ */
168064
+ class OpaWasmEvaluator {
168065
+ policy = null;
168066
+ dataDocument = {};
168067
+ compiler = new opa_compiler_1.OpaCompiler();
168068
+ async initialize(rulesPath) {
168069
+ const paths = Array.isArray(rulesPath) ? rulesPath : [rulesPath];
168070
+ const wasmBytes = await this.compiler.resolveWasmBytes(paths);
168071
+ try {
168072
+ // Use createRequire to load the optional dep at runtime without ncc bundling it.
168073
+ // `new Function('id', 'return require(id)')` fails in ncc bundles because
168074
+ // `require` is not in the `new Function` scope. `createRequire` works correctly
168075
+ // because it creates a real Node.js require rooted at the given path.
168076
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
168077
+ const { createRequire } = __nccwpck_require__(73339);
168078
+ const runtimeRequire = createRequire(__filename);
168079
+ const opaWasm = runtimeRequire('@open-policy-agent/opa-wasm');
168080
+ const loadPolicy = opaWasm.loadPolicy || opaWasm.default?.loadPolicy;
168081
+ if (!loadPolicy) {
168082
+ throw new Error('loadPolicy not found in @open-policy-agent/opa-wasm');
168083
+ }
168084
+ this.policy = await loadPolicy(wasmBytes);
168085
+ }
168086
+ catch (err) {
168087
+ if (err?.code === 'MODULE_NOT_FOUND' || err?.code === 'ERR_MODULE_NOT_FOUND') {
168088
+ throw new Error('OPA WASM evaluator requires @open-policy-agent/opa-wasm. ' +
168089
+ 'Install it with: npm install @open-policy-agent/opa-wasm');
168090
+ }
168091
+ throw err;
168092
+ }
168093
+ }
168094
+ /**
168095
+ * Load external data from a JSON file to use as the OPA data document.
168096
+ * The loaded data will be passed to `policy.setData()` during evaluation,
168097
+ * making it available in Rego via `data.<key>`.
168098
+ */
168099
+ loadData(dataPath) {
168100
+ const resolved = path.resolve(dataPath);
168101
+ if (path.normalize(resolved).includes('..')) {
168102
+ throw new Error(`Data path contains traversal sequences: ${dataPath}`);
168103
+ }
168104
+ if (!fs.existsSync(resolved)) {
168105
+ throw new Error(`OPA data file not found: ${resolved}`);
168106
+ }
168107
+ const stat = fs.statSync(resolved);
168108
+ if (stat.size > 10 * 1024 * 1024) {
168109
+ throw new Error(`OPA data file exceeds 10MB limit: ${resolved} (${stat.size} bytes)`);
168110
+ }
168111
+ const raw = fs.readFileSync(resolved, 'utf-8');
168112
+ try {
168113
+ const parsed = JSON.parse(raw);
168114
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
168115
+ throw new Error('OPA data file must contain a JSON object (not an array or primitive)');
168116
+ }
168117
+ this.dataDocument = parsed;
168118
+ }
168119
+ catch (err) {
168120
+ if (err.message.startsWith('OPA data file must')) {
168121
+ throw err;
168122
+ }
168123
+ throw new Error(`Failed to parse OPA data file ${resolved}: ${err.message}`);
168124
+ }
168125
+ }
168126
+ async evaluate(input) {
168127
+ if (!this.policy) {
168128
+ throw new Error('OPA WASM evaluator not initialized');
168129
+ }
168130
+ this.policy.setData(this.dataDocument);
168131
+ const resultSet = this.policy.evaluate(input);
168132
+ if (Array.isArray(resultSet) && resultSet.length > 0) {
168133
+ return resultSet[0].result;
168134
+ }
168135
+ return undefined;
168136
+ }
168137
+ async shutdown() {
168138
+ if (this.policy) {
168139
+ // opa-wasm policy objects may have a close/free method for WASM cleanup
168140
+ if (typeof this.policy.close === 'function') {
168141
+ try {
168142
+ this.policy.close();
168143
+ }
168144
+ catch { }
168145
+ }
168146
+ else if (typeof this.policy.free === 'function') {
168147
+ try {
168148
+ this.policy.free();
168149
+ }
168150
+ catch { }
168151
+ }
168152
+ }
168153
+ this.policy = null;
168154
+ }
168155
+ }
168156
+ exports.OpaWasmEvaluator = OpaWasmEvaluator;
168157
+
168158
+
168159
+ /***/ }),
168160
+
168161
+ /***/ 17117:
168162
+ /***/ ((__unused_webpack_module, exports) => {
168163
+
168164
+ "use strict";
168165
+
168166
+ /**
168167
+ * Copyright (c) ProbeLabs. All rights reserved.
168168
+ * Licensed under the Elastic License 2.0; you may not use this file except
168169
+ * in compliance with the Elastic License 2.0.
168170
+ */
168171
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
168172
+ exports.PolicyInputBuilder = void 0;
168173
+ /**
168174
+ * Builds OPA-compatible input documents from engine context.
168175
+ *
168176
+ * Resolves actor roles from the `policy.roles` config section by matching
168177
+ * the actor's authorAssociation and login against role definitions.
168178
+ */
168179
+ class PolicyInputBuilder {
168180
+ roles;
168181
+ actor;
168182
+ repository;
168183
+ pullRequest;
168184
+ constructor(policyConfig, actor, repository, pullRequest) {
168185
+ this.roles = policyConfig.roles || {};
168186
+ this.actor = actor;
168187
+ this.repository = repository;
168188
+ this.pullRequest = pullRequest;
168189
+ }
168190
+ /** Resolve which roles apply to the current actor. */
168191
+ resolveRoles() {
168192
+ const matched = [];
168193
+ for (const [roleName, roleConfig] of Object.entries(this.roles)) {
168194
+ let identityMatch = false;
168195
+ if (roleConfig.author_association &&
168196
+ this.actor.authorAssociation &&
168197
+ roleConfig.author_association.includes(this.actor.authorAssociation)) {
168198
+ identityMatch = true;
168199
+ }
168200
+ if (!identityMatch &&
168201
+ roleConfig.users &&
168202
+ this.actor.login &&
168203
+ roleConfig.users.includes(this.actor.login)) {
168204
+ identityMatch = true;
168205
+ }
168206
+ // Slack user ID match
168207
+ if (!identityMatch &&
168208
+ roleConfig.slack_users &&
168209
+ this.actor.slack?.userId &&
168210
+ roleConfig.slack_users.includes(this.actor.slack.userId)) {
168211
+ identityMatch = true;
168212
+ }
168213
+ // Email match (case-insensitive)
168214
+ if (!identityMatch && roleConfig.emails && this.actor.slack?.email) {
168215
+ const actorEmail = this.actor.slack.email.toLowerCase();
168216
+ if (roleConfig.emails.some(e => e.toLowerCase() === actorEmail)) {
168217
+ identityMatch = true;
168218
+ }
168219
+ }
168220
+ // Note: teams-based role resolution requires GitHub API access (read:org scope)
168221
+ // and is not yet implemented. If configured, the role will not match via teams.
168222
+ if (!identityMatch)
168223
+ continue;
168224
+ // slack_channels gate: if set, the role only applies when triggered from one of these channels
168225
+ if (roleConfig.slack_channels && roleConfig.slack_channels.length > 0) {
168226
+ if (!this.actor.slack?.channelId ||
168227
+ !roleConfig.slack_channels.includes(this.actor.slack.channelId)) {
168228
+ continue;
168229
+ }
168230
+ }
168231
+ matched.push(roleName);
168232
+ }
168233
+ return matched;
168234
+ }
168235
+ buildActor() {
168236
+ return {
168237
+ authorAssociation: this.actor.authorAssociation,
168238
+ login: this.actor.login,
168239
+ roles: this.resolveRoles(),
168240
+ isLocalMode: this.actor.isLocalMode,
168241
+ ...(this.actor.slack && { slack: this.actor.slack }),
168242
+ };
168243
+ }
168244
+ forCheckExecution(check) {
168245
+ return {
168246
+ scope: 'check.execute',
168247
+ check: {
168248
+ id: check.id,
168249
+ type: check.type,
168250
+ group: check.group,
168251
+ tags: check.tags,
168252
+ criticality: check.criticality,
168253
+ sandbox: check.sandbox,
168254
+ policy: check.policy,
168255
+ },
168256
+ actor: this.buildActor(),
168257
+ repository: this.repository,
168258
+ pullRequest: this.pullRequest,
168259
+ };
168260
+ }
168261
+ forToolInvocation(serverName, methodName, transport) {
168262
+ return {
168263
+ scope: 'tool.invoke',
168264
+ tool: { serverName, methodName, transport },
168265
+ actor: this.buildActor(),
168266
+ repository: this.repository,
168267
+ pullRequest: this.pullRequest,
168268
+ };
168269
+ }
168270
+ forCapabilityResolve(checkId, capabilities) {
168271
+ return {
168272
+ scope: 'capability.resolve',
168273
+ check: { id: checkId, type: 'ai' },
168274
+ capability: capabilities,
168275
+ actor: this.buildActor(),
168276
+ repository: this.repository,
168277
+ pullRequest: this.pullRequest,
168278
+ };
168279
+ }
168280
+ }
168281
+ exports.PolicyInputBuilder = PolicyInputBuilder;
168282
+
168283
+
168284
+ /***/ }),
168285
+
168286
+ /***/ 63737:
168287
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
168288
+
168289
+ "use strict";
168290
+
168291
+ /**
168292
+ * Copyright (c) ProbeLabs. All rights reserved.
168293
+ * Licensed under the Elastic License 2.0; you may not use this file except
168294
+ * in compliance with the Elastic License 2.0.
168295
+ */
168296
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
168297
+ if (k2 === undefined) k2 = k;
168298
+ var desc = Object.getOwnPropertyDescriptor(m, k);
168299
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
168300
+ desc = { enumerable: true, get: function() { return m[k]; } };
168301
+ }
168302
+ Object.defineProperty(o, k2, desc);
168303
+ }) : (function(o, m, k, k2) {
168304
+ if (k2 === undefined) k2 = k;
168305
+ o[k2] = m[k];
168306
+ }));
168307
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
168308
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
168309
+ }) : function(o, v) {
168310
+ o["default"] = v;
168311
+ });
168312
+ var __importStar = (this && this.__importStar) || (function () {
168313
+ var ownKeys = function(o) {
168314
+ ownKeys = Object.getOwnPropertyNames || function (o) {
168315
+ var ar = [];
168316
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
168317
+ return ar;
168318
+ };
168319
+ return ownKeys(o);
168320
+ };
168321
+ return function (mod) {
168322
+ if (mod && mod.__esModule) return mod;
168323
+ var result = {};
168324
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
168325
+ __setModuleDefault(result, mod);
168326
+ return result;
168327
+ };
168328
+ })();
168329
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
168330
+ exports.KnexStoreBackend = void 0;
168331
+ /**
168332
+ * Knex-backed schedule store for PostgreSQL, MySQL, and MSSQL (Enterprise)
168333
+ *
168334
+ * Uses Knex query builder for database-agnostic SQL. Same schema as SQLite backend
168335
+ * but with real distributed locking via row-level claims (claimed_by/claimed_at/lock_token).
168336
+ */
168337
+ const fs = __importStar(__nccwpck_require__(79896));
168338
+ const path = __importStar(__nccwpck_require__(16928));
168339
+ const uuid_1 = __nccwpck_require__(31914);
168340
+ const logger_1 = __nccwpck_require__(86999);
168341
+ function toNum(val) {
168342
+ if (val === null || val === undefined)
168343
+ return undefined;
168344
+ return typeof val === 'string' ? parseInt(val, 10) : val;
168345
+ }
168346
+ function safeJsonParse(value) {
168347
+ if (!value)
168348
+ return undefined;
168349
+ try {
168350
+ return JSON.parse(value);
168351
+ }
168352
+ catch {
168353
+ return undefined;
168354
+ }
168355
+ }
168356
+ function fromTriggerRow(row) {
168357
+ return {
168358
+ id: row.id,
168359
+ creatorId: row.creator_id,
168360
+ creatorContext: row.creator_context ?? undefined,
168361
+ creatorName: row.creator_name ?? undefined,
168362
+ description: row.description ?? undefined,
168363
+ channels: safeJsonParse(row.channels),
168364
+ fromUsers: safeJsonParse(row.from_users),
168365
+ fromBots: row.from_bots === true || row.from_bots === 1,
168366
+ contains: safeJsonParse(row.contains),
168367
+ matchPattern: row.match_pattern ?? undefined,
168368
+ threads: row.threads,
168369
+ workflow: row.workflow,
168370
+ inputs: safeJsonParse(row.inputs),
168371
+ outputContext: safeJsonParse(row.output_context),
168372
+ status: row.status,
168373
+ enabled: row.enabled === true || row.enabled === 1,
168374
+ createdAt: toNum(row.created_at),
168375
+ };
168376
+ }
168377
+ function toTriggerInsertRow(trigger) {
168378
+ return {
168379
+ id: trigger.id,
168380
+ creator_id: trigger.creatorId,
168381
+ creator_context: trigger.creatorContext ?? null,
168382
+ creator_name: trigger.creatorName ?? null,
168383
+ description: trigger.description ?? null,
168384
+ channels: trigger.channels ? JSON.stringify(trigger.channels) : null,
168385
+ from_users: trigger.fromUsers ? JSON.stringify(trigger.fromUsers) : null,
168386
+ from_bots: trigger.fromBots,
168387
+ contains: trigger.contains ? JSON.stringify(trigger.contains) : null,
168388
+ match_pattern: trigger.matchPattern ?? null,
168389
+ threads: trigger.threads,
168390
+ workflow: trigger.workflow,
168391
+ inputs: trigger.inputs ? JSON.stringify(trigger.inputs) : null,
168392
+ output_context: trigger.outputContext ? JSON.stringify(trigger.outputContext) : null,
168393
+ status: trigger.status,
168394
+ enabled: trigger.enabled,
168395
+ created_at: trigger.createdAt,
168396
+ };
168397
+ }
168398
+ function fromDbRow(row) {
168399
+ return {
168400
+ id: row.id,
168401
+ creatorId: row.creator_id,
168402
+ creatorContext: row.creator_context ?? undefined,
168403
+ creatorName: row.creator_name ?? undefined,
168404
+ timezone: row.timezone,
168405
+ schedule: row.schedule_expr,
168406
+ runAt: toNum(row.run_at),
168407
+ isRecurring: row.is_recurring === true || row.is_recurring === 1,
168408
+ originalExpression: row.original_expression,
168409
+ workflow: row.workflow ?? undefined,
168410
+ workflowInputs: safeJsonParse(row.workflow_inputs),
168411
+ outputContext: safeJsonParse(row.output_context),
168412
+ status: row.status,
168413
+ createdAt: toNum(row.created_at),
168414
+ lastRunAt: toNum(row.last_run_at),
168415
+ nextRunAt: toNum(row.next_run_at),
168416
+ runCount: row.run_count,
168417
+ failureCount: row.failure_count,
168418
+ lastError: row.last_error ?? undefined,
168419
+ previousResponse: row.previous_response ?? undefined,
168420
+ };
168421
+ }
168422
+ function toInsertRow(schedule) {
168423
+ return {
168424
+ id: schedule.id,
168425
+ creator_id: schedule.creatorId,
168426
+ creator_context: schedule.creatorContext ?? null,
168427
+ creator_name: schedule.creatorName ?? null,
168428
+ timezone: schedule.timezone,
168429
+ schedule_expr: schedule.schedule,
168430
+ run_at: schedule.runAt ?? null,
168431
+ is_recurring: schedule.isRecurring,
168432
+ original_expression: schedule.originalExpression,
168433
+ workflow: schedule.workflow ?? null,
168434
+ workflow_inputs: schedule.workflowInputs ? JSON.stringify(schedule.workflowInputs) : null,
168435
+ output_context: schedule.outputContext ? JSON.stringify(schedule.outputContext) : null,
168436
+ status: schedule.status,
168437
+ created_at: schedule.createdAt,
168438
+ last_run_at: schedule.lastRunAt ?? null,
168439
+ next_run_at: schedule.nextRunAt ?? null,
168440
+ run_count: schedule.runCount,
168441
+ failure_count: schedule.failureCount,
168442
+ last_error: schedule.lastError ?? null,
168443
+ previous_response: schedule.previousResponse ?? null,
168444
+ };
168445
+ }
168446
+ /**
168447
+ * Enterprise Knex-backed store for PostgreSQL, MySQL, and MSSQL
168448
+ */
168449
+ class KnexStoreBackend {
168450
+ knex = null;
168451
+ driver;
168452
+ connection;
168453
+ constructor(driver, storageConfig, _haConfig) {
168454
+ this.driver = driver;
168455
+ this.connection = (storageConfig.connection || {});
168456
+ }
168457
+ async initialize() {
168458
+ // Load knex dynamically
168459
+ const { createRequire } = __nccwpck_require__(73339);
168460
+ const runtimeRequire = createRequire(__filename);
168461
+ let knexFactory;
168462
+ try {
168463
+ knexFactory = runtimeRequire('knex');
168464
+ }
168465
+ catch (err) {
168466
+ const code = err?.code;
168467
+ if (code === 'MODULE_NOT_FOUND' || code === 'ERR_MODULE_NOT_FOUND') {
168468
+ throw new Error('knex is required for PostgreSQL/MySQL/MSSQL schedule storage. ' +
168469
+ 'Install it with: npm install knex');
168470
+ }
168471
+ throw err;
168472
+ }
168473
+ const clientMap = {
168474
+ postgresql: 'pg',
168475
+ mysql: 'mysql2',
168476
+ mssql: 'tedious',
168477
+ };
168478
+ const client = clientMap[this.driver];
168479
+ // Build connection config
168480
+ let connection;
168481
+ if (this.connection.connection_string) {
168482
+ connection = this.connection.connection_string;
168483
+ }
168484
+ else if (this.driver === 'mssql') {
168485
+ connection = this.buildMssqlConnection();
168486
+ }
168487
+ else {
168488
+ connection = this.buildStandardConnection();
168489
+ }
168490
+ this.knex = knexFactory({
168491
+ client,
168492
+ connection,
168493
+ pool: {
168494
+ min: this.connection.pool?.min ?? 0,
168495
+ max: this.connection.pool?.max ?? 10,
168496
+ },
168497
+ });
168498
+ // Run schema migration
168499
+ await this.migrateSchema();
168500
+ logger_1.logger.info(`[KnexStore] Initialized (${this.driver})`);
168501
+ }
168502
+ buildStandardConnection() {
168503
+ return {
168504
+ host: this.connection.host || 'localhost',
168505
+ port: this.connection.port,
168506
+ database: this.connection.database || 'visor',
168507
+ user: this.connection.user,
168508
+ password: this.connection.password,
168509
+ ssl: this.resolveSslConfig(),
168510
+ };
168511
+ }
168512
+ buildMssqlConnection() {
168513
+ const ssl = this.connection.ssl;
168514
+ const sslEnabled = ssl === true || (typeof ssl === 'object' && ssl.enabled !== false);
168515
+ return {
168516
+ server: this.connection.host || 'localhost',
168517
+ port: this.connection.port,
168518
+ database: this.connection.database || 'visor',
168519
+ user: this.connection.user,
168520
+ password: this.connection.password,
168521
+ options: {
168522
+ encrypt: sslEnabled,
168523
+ trustServerCertificate: typeof ssl === 'object' ? ssl.reject_unauthorized === false : !sslEnabled,
168524
+ },
168525
+ };
168526
+ }
168527
+ resolveSslConfig() {
168528
+ const ssl = this.connection.ssl;
168529
+ if (ssl === false || ssl === undefined)
168530
+ return false;
168531
+ if (ssl === true)
168532
+ return { rejectUnauthorized: true };
168533
+ // Object config
168534
+ if (ssl.enabled === false)
168535
+ return false;
168536
+ const result = {
168537
+ rejectUnauthorized: ssl.reject_unauthorized !== false,
168538
+ };
168539
+ if (ssl.ca) {
168540
+ const caPath = this.validateSslPath(ssl.ca, 'CA certificate');
168541
+ result.ca = fs.readFileSync(caPath, 'utf8');
168542
+ }
168543
+ if (ssl.cert) {
168544
+ const certPath = this.validateSslPath(ssl.cert, 'client certificate');
168545
+ result.cert = fs.readFileSync(certPath, 'utf8');
168546
+ }
168547
+ if (ssl.key) {
168548
+ const keyPath = this.validateSslPath(ssl.key, 'client key');
168549
+ result.key = fs.readFileSync(keyPath, 'utf8');
168550
+ }
168551
+ return result;
168552
+ }
168553
+ validateSslPath(filePath, label) {
168554
+ const resolved = path.resolve(filePath);
168555
+ if (resolved !== path.normalize(resolved)) {
168556
+ throw new Error(`SSL ${label} path contains invalid sequences: ${filePath}`);
168557
+ }
168558
+ if (!fs.existsSync(resolved)) {
168559
+ throw new Error(`SSL ${label} not found: ${filePath}`);
168560
+ }
168561
+ return resolved;
168562
+ }
168563
+ async shutdown() {
168564
+ if (this.knex) {
168565
+ await this.knex.destroy();
168566
+ this.knex = null;
168567
+ }
168568
+ }
168569
+ async migrateSchema() {
168570
+ const knex = this.getKnex();
168571
+ const exists = await knex.schema.hasTable('schedules');
168572
+ if (!exists) {
168573
+ await knex.schema.createTable('schedules', table => {
168574
+ table.string('id', 36).primary();
168575
+ table.string('creator_id', 255).notNullable().index();
168576
+ table.string('creator_context', 255);
168577
+ table.string('creator_name', 255);
168578
+ table.string('timezone', 64).notNullable().defaultTo('UTC');
168579
+ table.string('schedule_expr', 255);
168580
+ table.bigInteger('run_at');
168581
+ table.boolean('is_recurring').notNullable();
168582
+ table.text('original_expression');
168583
+ table.string('workflow', 255);
168584
+ table.text('workflow_inputs');
168585
+ table.text('output_context');
168586
+ table.string('status', 20).notNullable().index();
168587
+ table.bigInteger('created_at').notNullable();
168588
+ table.bigInteger('last_run_at');
168589
+ table.bigInteger('next_run_at');
168590
+ table.integer('run_count').notNullable().defaultTo(0);
168591
+ table.integer('failure_count').notNullable().defaultTo(0);
168592
+ table.text('last_error');
168593
+ table.text('previous_response');
168594
+ table.index(['status', 'next_run_at']);
168595
+ });
168596
+ }
168597
+ // Create message_triggers table
168598
+ const triggersExist = await knex.schema.hasTable('message_triggers');
168599
+ if (!triggersExist) {
168600
+ await knex.schema.createTable('message_triggers', table => {
168601
+ table.string('id', 36).primary();
168602
+ table.string('creator_id', 255).notNullable().index();
168603
+ table.string('creator_context', 255);
168604
+ table.string('creator_name', 255);
168605
+ table.text('description');
168606
+ table.text('channels'); // JSON array
168607
+ table.text('from_users'); // JSON array
168608
+ table.boolean('from_bots').notNullable().defaultTo(false);
168609
+ table.text('contains'); // JSON array
168610
+ table.text('match_pattern');
168611
+ table.string('threads', 20).notNullable().defaultTo('any');
168612
+ table.string('workflow', 255).notNullable();
168613
+ table.text('inputs'); // JSON
168614
+ table.text('output_context'); // JSON
168615
+ table.string('status', 20).notNullable().defaultTo('active').index();
168616
+ table.boolean('enabled').notNullable().defaultTo(true);
168617
+ table.bigInteger('created_at').notNullable();
168618
+ });
168619
+ }
168620
+ // Create scheduler_locks table for distributed locking
168621
+ const locksExist = await knex.schema.hasTable('scheduler_locks');
168622
+ if (!locksExist) {
168623
+ await knex.schema.createTable('scheduler_locks', table => {
168624
+ table.string('lock_id', 255).primary();
168625
+ table.string('node_id', 255).notNullable();
168626
+ table.string('lock_token', 36).notNullable();
168627
+ table.bigInteger('acquired_at').notNullable();
168628
+ table.bigInteger('expires_at').notNullable();
168629
+ });
168630
+ }
168631
+ }
168632
+ getKnex() {
168633
+ if (!this.knex) {
168634
+ throw new Error('[KnexStore] Not initialized. Call initialize() first.');
168635
+ }
168636
+ return this.knex;
168637
+ }
168638
+ // --- CRUD ---
168639
+ async create(schedule) {
168640
+ const knex = this.getKnex();
168641
+ const newSchedule = {
168642
+ ...schedule,
168643
+ id: (0, uuid_1.v4)(),
168644
+ createdAt: Date.now(),
168645
+ runCount: 0,
168646
+ failureCount: 0,
168647
+ status: 'active',
168648
+ };
168649
+ await knex('schedules').insert(toInsertRow(newSchedule));
168650
+ logger_1.logger.info(`[KnexStore] Created schedule ${newSchedule.id} for user ${newSchedule.creatorId}`);
168651
+ return newSchedule;
168652
+ }
168653
+ async importSchedule(schedule) {
168654
+ const knex = this.getKnex();
168655
+ const existing = await knex('schedules').where('id', schedule.id).first();
168656
+ if (existing)
168657
+ return; // Already imported (idempotent)
168658
+ await knex('schedules').insert(toInsertRow(schedule));
168659
+ }
168660
+ async get(id) {
168661
+ const knex = this.getKnex();
168662
+ const row = await knex('schedules').where('id', id).first();
168663
+ return row ? fromDbRow(row) : undefined;
168664
+ }
168665
+ async update(id, patch) {
168666
+ const knex = this.getKnex();
168667
+ const existing = await knex('schedules').where('id', id).first();
168668
+ if (!existing)
168669
+ return undefined;
168670
+ const current = fromDbRow(existing);
168671
+ const updated = { ...current, ...patch, id: current.id };
168672
+ const row = toInsertRow(updated);
168673
+ // Remove id from update (PK cannot change)
168674
+ delete row.id;
168675
+ await knex('schedules').where('id', id).update(row);
168676
+ return updated;
168677
+ }
168678
+ async delete(id) {
168679
+ const knex = this.getKnex();
168680
+ const deleted = await knex('schedules').where('id', id).del();
168681
+ if (deleted > 0) {
168682
+ logger_1.logger.info(`[KnexStore] Deleted schedule ${id}`);
168683
+ return true;
168684
+ }
168685
+ return false;
168686
+ }
168687
+ // --- Queries ---
168688
+ async getByCreator(creatorId) {
168689
+ const knex = this.getKnex();
168690
+ const rows = await knex('schedules').where('creator_id', creatorId);
168691
+ return rows.map((r) => fromDbRow(r));
168692
+ }
168693
+ async getActiveSchedules() {
168694
+ const knex = this.getKnex();
168695
+ const rows = await knex('schedules').where('status', 'active');
168696
+ return rows.map((r) => fromDbRow(r));
168697
+ }
168698
+ async getDueSchedules(now) {
168699
+ const ts = now ?? Date.now();
168700
+ const knex = this.getKnex();
168701
+ // MSSQL uses 1/0 for booleans
168702
+ const bFalse = this.driver === 'mssql' ? 0 : false;
168703
+ const bTrue = this.driver === 'mssql' ? 1 : true;
168704
+ const rows = await knex('schedules')
168705
+ .where('status', 'active')
168706
+ .andWhere(function () {
168707
+ this.where(function () {
168708
+ this.where('is_recurring', bFalse)
168709
+ .whereNotNull('run_at')
168710
+ .where('run_at', '<=', ts);
168711
+ }).orWhere(function () {
168712
+ this.where('is_recurring', bTrue)
168713
+ .whereNotNull('next_run_at')
168714
+ .where('next_run_at', '<=', ts);
168715
+ });
168716
+ });
168717
+ return rows.map((r) => fromDbRow(r));
168718
+ }
168719
+ async findByWorkflow(creatorId, workflowName) {
168720
+ const knex = this.getKnex();
168721
+ const escaped = workflowName.toLowerCase().replace(/[%_\\]/g, '\\$&');
168722
+ const pattern = `%${escaped}%`;
168723
+ const rows = await knex('schedules')
168724
+ .where('creator_id', creatorId)
168725
+ .where('status', 'active')
168726
+ .whereRaw("LOWER(workflow) LIKE ? ESCAPE '\\'", [pattern]);
168727
+ return rows.map((r) => fromDbRow(r));
168728
+ }
168729
+ async getAll() {
168730
+ const knex = this.getKnex();
168731
+ const rows = await knex('schedules');
168732
+ return rows.map((r) => fromDbRow(r));
168733
+ }
168734
+ async getStats() {
168735
+ const knex = this.getKnex();
168736
+ // MSSQL uses 1/0 for booleans; PostgreSQL/MySQL accept both true/1
168737
+ const boolTrue = this.driver === 'mssql' ? '1' : 'true';
168738
+ const boolFalse = this.driver === 'mssql' ? '0' : 'false';
168739
+ const result = await knex('schedules')
168740
+ .select(knex.raw('COUNT(*) as total'), knex.raw("SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active"), knex.raw("SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused"), knex.raw("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed"), knex.raw("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed"), knex.raw(`SUM(CASE WHEN is_recurring = ${boolTrue} THEN 1 ELSE 0 END) as recurring`), knex.raw(`SUM(CASE WHEN is_recurring = ${boolFalse} THEN 1 ELSE 0 END) as one_time`))
168741
+ .first();
168742
+ return {
168743
+ total: Number(result.total) || 0,
168744
+ active: Number(result.active) || 0,
168745
+ paused: Number(result.paused) || 0,
168746
+ completed: Number(result.completed) || 0,
168747
+ failed: Number(result.failed) || 0,
168748
+ recurring: Number(result.recurring) || 0,
168749
+ oneTime: Number(result.one_time) || 0,
168750
+ };
168751
+ }
168752
+ async validateLimits(creatorId, isRecurring, limits) {
168753
+ const knex = this.getKnex();
168754
+ if (limits.maxGlobal) {
168755
+ const result = await knex('schedules').count('* as cnt').first();
168756
+ if (Number(result?.cnt) >= limits.maxGlobal) {
168757
+ throw new Error(`Global schedule limit reached (${limits.maxGlobal})`);
168758
+ }
168759
+ }
168760
+ if (limits.maxPerUser) {
168761
+ const result = await knex('schedules')
168762
+ .where('creator_id', creatorId)
168763
+ .count('* as cnt')
168764
+ .first();
168765
+ if (Number(result?.cnt) >= limits.maxPerUser) {
168766
+ throw new Error(`You have reached the maximum number of schedules (${limits.maxPerUser})`);
168767
+ }
168768
+ }
168769
+ if (isRecurring && limits.maxRecurringPerUser) {
168770
+ const bTrue = this.driver === 'mssql' ? 1 : true;
168771
+ const result = await knex('schedules')
168772
+ .where('creator_id', creatorId)
168773
+ .where('is_recurring', bTrue)
168774
+ .count('* as cnt')
168775
+ .first();
168776
+ if (Number(result?.cnt) >= limits.maxRecurringPerUser) {
168777
+ throw new Error(`You have reached the maximum number of recurring schedules (${limits.maxRecurringPerUser})`);
168778
+ }
168779
+ }
168780
+ }
168781
+ // --- HA Distributed Locking (via scheduler_locks table) ---
168782
+ async tryAcquireLock(lockId, nodeId, ttlSeconds) {
168783
+ const knex = this.getKnex();
168784
+ const now = Date.now();
168785
+ const expiresAt = now + ttlSeconds * 1000;
168786
+ const token = (0, uuid_1.v4)();
168787
+ // Step 1: Try to claim an existing expired lock
168788
+ const updated = await knex('scheduler_locks')
168789
+ .where('lock_id', lockId)
168790
+ .where('expires_at', '<', now)
168791
+ .update({
168792
+ node_id: nodeId,
168793
+ lock_token: token,
168794
+ acquired_at: now,
168795
+ expires_at: expiresAt,
168796
+ });
168797
+ if (updated > 0)
168798
+ return token;
168799
+ // Step 2: Try to INSERT a new lock row
168800
+ try {
168801
+ await knex('scheduler_locks').insert({
168802
+ lock_id: lockId,
168803
+ node_id: nodeId,
168804
+ lock_token: token,
168805
+ acquired_at: now,
168806
+ expires_at: expiresAt,
168807
+ });
168808
+ return token;
168809
+ }
168810
+ catch {
168811
+ // Unique constraint violation — another node holds the lock
168812
+ return null;
168813
+ }
168814
+ }
168815
+ async releaseLock(lockId, lockToken) {
168816
+ const knex = this.getKnex();
168817
+ await knex('scheduler_locks').where('lock_id', lockId).where('lock_token', lockToken).del();
168818
+ }
168819
+ async renewLock(lockId, lockToken, ttlSeconds) {
168820
+ const knex = this.getKnex();
168821
+ const now = Date.now();
168822
+ const expiresAt = now + ttlSeconds * 1000;
168823
+ const updated = await knex('scheduler_locks')
168824
+ .where('lock_id', lockId)
168825
+ .where('lock_token', lockToken)
168826
+ .update({ acquired_at: now, expires_at: expiresAt });
168827
+ return updated > 0;
168828
+ }
168829
+ async flush() {
168830
+ // No-op for server-based backends
168831
+ }
168832
+ // --- Message Trigger CRUD ---
168833
+ async createTrigger(trigger) {
168834
+ const knex = this.getKnex();
168835
+ const newTrigger = {
168836
+ ...trigger,
168837
+ id: (0, uuid_1.v4)(),
168838
+ createdAt: Date.now(),
168839
+ };
168840
+ await knex('message_triggers').insert(toTriggerInsertRow(newTrigger));
168841
+ logger_1.logger.info(`[KnexStore] Created trigger ${newTrigger.id} for user ${newTrigger.creatorId}`);
168842
+ return newTrigger;
168843
+ }
168844
+ async getTrigger(id) {
168845
+ const knex = this.getKnex();
168846
+ const row = await knex('message_triggers').where('id', id).first();
168847
+ return row ? fromTriggerRow(row) : undefined;
168848
+ }
168849
+ async updateTrigger(id, patch) {
168850
+ const knex = this.getKnex();
168851
+ const existing = await knex('message_triggers').where('id', id).first();
168852
+ if (!existing)
168853
+ return undefined;
168854
+ const current = fromTriggerRow(existing);
168855
+ const updated = {
168856
+ ...current,
168857
+ ...patch,
168858
+ id: current.id,
168859
+ createdAt: current.createdAt,
168860
+ };
168861
+ const row = toTriggerInsertRow(updated);
168862
+ delete row.id;
168863
+ await knex('message_triggers').where('id', id).update(row);
168864
+ return updated;
168865
+ }
168866
+ async deleteTrigger(id) {
168867
+ const knex = this.getKnex();
168868
+ const deleted = await knex('message_triggers').where('id', id).del();
168869
+ if (deleted > 0) {
168870
+ logger_1.logger.info(`[KnexStore] Deleted trigger ${id}`);
168871
+ return true;
168872
+ }
168873
+ return false;
168874
+ }
168875
+ async getTriggersByCreator(creatorId) {
168876
+ const knex = this.getKnex();
168877
+ const rows = await knex('message_triggers').where('creator_id', creatorId);
168878
+ return rows.map((r) => fromTriggerRow(r));
168879
+ }
168880
+ async getActiveTriggers() {
168881
+ const knex = this.getKnex();
168882
+ const rows = await knex('message_triggers')
168883
+ .where('status', 'active')
168884
+ .where('enabled', this.driver === 'mssql' ? 1 : true);
168885
+ return rows.map((r) => fromTriggerRow(r));
168886
+ }
168887
+ }
168888
+ exports.KnexStoreBackend = KnexStoreBackend;
168889
+
168890
+
167087
168891
  /***/ }),
167088
168892
 
167089
168893
  /***/ 83864:
@@ -178087,6 +179891,35 @@ class OutputFormatters {
178087
179891
  exports.OutputFormatters = OutputFormatters;
178088
179892
 
178089
179893
 
179894
+ /***/ }),
179895
+
179896
+ /***/ 93866:
179897
+ /***/ ((__unused_webpack_module, exports) => {
179898
+
179899
+ "use strict";
179900
+
179901
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
179902
+ exports.DefaultPolicyEngine = void 0;
179903
+ /**
179904
+ * Default (no-op) policy engine — always allows everything.
179905
+ * Used when no enterprise license is present or policy is disabled.
179906
+ */
179907
+ class DefaultPolicyEngine {
179908
+ async initialize(_config) { }
179909
+ async evaluateCheckExecution(_checkId, _checkConfig) {
179910
+ return { allowed: true };
179911
+ }
179912
+ async evaluateToolInvocation(_serverName, _methodName, _transport) {
179913
+ return { allowed: true };
179914
+ }
179915
+ async evaluateCapabilities(_checkId, _capabilities) {
179916
+ return { allowed: true };
179917
+ }
179918
+ async shutdown() { }
179919
+ }
179920
+ exports.DefaultPolicyEngine = DefaultPolicyEngine;
179921
+
179922
+
178090
179923
  /***/ }),
178091
179924
 
178092
179925
  /***/ 96611:
@@ -188256,6 +190089,15 @@ class CustomToolsSSEServer {
188256
190089
  original_expression: args.original_expression,
188257
190090
  // For cancel/pause/resume
188258
190091
  schedule_id: args.schedule_id,
190092
+ // For trigger actions
190093
+ trigger_channels: args.trigger_channels,
190094
+ trigger_from: args.trigger_from,
190095
+ trigger_from_bots: args.trigger_from_bots,
190096
+ trigger_contains: args.trigger_contains,
190097
+ trigger_match: args.trigger_match,
190098
+ trigger_threads: args.trigger_threads,
190099
+ trigger_description: args.trigger_description,
190100
+ trigger_id: args.trigger_id,
188259
190101
  };
188260
190102
  const scheduleResult = await (0, schedule_tool_1.handleScheduleAction)(scheduleArgs, scheduleContext);
188261
190103
  result = scheduleResult.success
@@ -194160,19 +196002,13 @@ function formatTrigger(trigger) {
194160
196002
  * Handle create_trigger action
194161
196003
  */
194162
196004
  async function handleCreateTrigger(args, context, store) {
194163
- // Validate workflow
194164
- if (!args.workflow) {
194165
- return {
194166
- success: false,
194167
- message: 'Missing workflow',
194168
- error: 'Please specify the workflow to run when the trigger fires.',
194169
- };
194170
- }
196005
+ // Default workflow to "default" if not specified
196006
+ const workflow = args.workflow || 'default';
194171
196007
  // Validate workflow exists if we have available workflows
194172
- if (context.availableWorkflows && !context.availableWorkflows.includes(args.workflow)) {
196008
+ if (context.availableWorkflows && !context.availableWorkflows.includes(workflow)) {
194173
196009
  return {
194174
196010
  success: false,
194175
- message: `Workflow "${args.workflow}" not found`,
196011
+ message: `Workflow "${workflow}" not found`,
194176
196012
  error: `Available workflows: ${context.availableWorkflows.slice(0, 5).join(', ')}${context.availableWorkflows.length > 5 ? '...' : ''}`,
194177
196013
  };
194178
196014
  }
@@ -194188,7 +196024,7 @@ async function handleCreateTrigger(args, context, store) {
194188
196024
  };
194189
196025
  }
194190
196026
  // Check permissions for the workflow
194191
- const permissionCheck = checkSchedulePermissions(context, args.workflow);
196027
+ const permissionCheck = checkSchedulePermissions(context, workflow);
194192
196028
  if (!permissionCheck.allowed) {
194193
196029
  return {
194194
196030
  success: false,
@@ -194208,12 +196044,12 @@ async function handleCreateTrigger(args, context, store) {
194208
196044
  contains: args.trigger_contains,
194209
196045
  matchPattern: args.trigger_match,
194210
196046
  threads: args.trigger_threads ?? 'any',
194211
- workflow: args.workflow,
196047
+ workflow: workflow,
194212
196048
  inputs: args.workflow_inputs,
194213
196049
  status: 'active',
194214
196050
  enabled: true,
194215
196051
  });
194216
- logger_1.logger.info(`[ScheduleTool] Created message trigger ${trigger.id} for user ${context.userId}: workflow="${args.workflow}"`);
196052
+ logger_1.logger.info(`[ScheduleTool] Created message trigger ${trigger.id} for user ${context.userId}: workflow="${workflow}"`);
194217
196053
  return {
194218
196054
  success: true,
194219
196055
  message: `**Message trigger created!**
@@ -194346,12 +196182,17 @@ function getScheduleToolDefinition() {
194346
196182
 
194347
196183
  YOU (the AI) must extract and structure all scheduling parameters. Do NOT pass natural language time expressions - convert them to cron or ISO timestamps.
194348
196184
 
194349
- CRITICAL WORKFLOW RULE:
196185
+ CRITICAL WORKFLOW RULE (for 'create' action only):
194350
196186
  - To schedule a WORKFLOW, the user MUST use a '%' prefix (e.g., "schedule %my-workflow daily").
194351
196187
  - If the '%' prefix is present, extract the word following it as the 'workflow' parameter (without the '%').
194352
196188
  - If the '%' prefix is NOT present, the request is a simple text reminder. The ENTIRE user request (excluding the schedule expression) MUST be placed in the 'reminder_text' parameter.
194353
196189
  - DO NOT guess or infer a workflow name from a user's request without the '%' prefix.
194354
196190
 
196191
+ WORKFLOW RULE FOR TRIGGERS (create_trigger action):
196192
+ - Triggers ALWAYS require a workflow. The '%' prefix rule does NOT apply to triggers.
196193
+ - If the user specifies a workflow name (with or without '%'), use it directly.
196194
+ - If the user does NOT specify a workflow name, use "default" as the workflow name.
196195
+
194355
196196
  ACTIONS:
194356
196197
  - create: Schedule a new reminder or workflow
194357
196198
  - list: Show user's active schedules
@@ -194364,7 +196205,7 @@ Slack messages in specific channels. Use the create_trigger, list_triggers, dele
194364
196205
  actions for this. Message triggers fire workflows based on message content, channel, sender, and thread scope.
194365
196206
 
194366
196207
  TRIGGER ACTIONS:
194367
- - create_trigger: Create a new message trigger (requires workflow + at least one filter). Supports filtering by user IDs (trigger_from), channels, keywords, regex, and thread scope.
196208
+ - create_trigger: Create a new message trigger (requires at least one filter; workflow defaults to "default" if not specified). Supports filtering by user IDs (trigger_from), channels, keywords, regex, and thread scope.
194368
196209
  - list_triggers: Show user's message triggers
194369
196210
  - delete_trigger: Remove a trigger by ID
194370
196211
  - update_trigger: Enable/disable a trigger by ID
@@ -194464,6 +196305,9 @@ User: "watch #cicd for messages containing 'failed' and run %handle-cicd"
194464
196305
  User: "trigger on each of my messages in this channel and run %auto-reply" (user ID is U3P2L4XNE)
194465
196306
  → { "action": "create_trigger", "trigger_channels": ["C09V810NY6R"], "trigger_from": ["U3P2L4XNE"], "workflow": "auto-reply" }
194466
196307
 
196308
+ User: "trigger on each message in this channel" (no workflow specified — use "default")
196309
+ → { "action": "create_trigger", "trigger_channels": ["C09V810NY6R"], "workflow": "default" }
196310
+
194467
196311
  User: "list my message triggers"
194468
196312
  → { "action": "list_triggers" }
194469
196313
 
@@ -194497,7 +196341,7 @@ User: "disable trigger abc123"
194497
196341
  },
194498
196342
  workflow: {
194499
196343
  type: 'string',
194500
- description: 'For create: workflow ID to run. ONLY populate this if the user used the % prefix (e.g., "%my-workflow"). Extract the name without the % symbol. If no % prefix, use reminder_text instead.',
196344
+ description: 'For create: workflow ID to run. ONLY populate this if the user used the % prefix (e.g., "%my-workflow"). Extract the name without the % symbol. If no % prefix, use reminder_text instead. For create_trigger: workflow is REQUIRED — use the workflow name the user specified (% prefix optional), or "default" if not specified.',
194501
196345
  },
194502
196346
  workflow_inputs: {
194503
196347
  type: 'object',
@@ -198079,6 +199923,15 @@ async function executeScheduleTool(args, slackContext, slackClient, availableWor
198079
199923
  original_expression: args.original_expression,
198080
199924
  // For cancel/pause/resume
198081
199925
  schedule_id: args.schedule_id,
199926
+ // For trigger actions
199927
+ trigger_channels: args.trigger_channels,
199928
+ trigger_from: args.trigger_from,
199929
+ trigger_from_bots: args.trigger_from_bots,
199930
+ trigger_contains: args.trigger_contains,
199931
+ trigger_match: args.trigger_match,
199932
+ trigger_threads: args.trigger_threads,
199933
+ trigger_description: args.trigger_description,
199934
+ trigger_id: args.trigger_id,
198082
199935
  };
198083
199936
  // If AI didn't provide target, default to current Slack context
198084
199937
  if (!toolArgs.target_type && slackContext.channel) {
@@ -199751,7 +201604,7 @@ class StateMachineExecutionEngine {
199751
201604
  try {
199752
201605
  logger_1.logger.debug(`[PolicyEngine] Loading enterprise policy engine (engine=${configWithTagFilter.policy.engine})`);
199753
201606
  // @ts-ignore — enterprise/ may not exist in OSS builds (caught at runtime)
199754
- const { loadEnterprisePolicyEngine } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(7065)));
201607
+ const { loadEnterprisePolicyEngine } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(87068)));
199755
201608
  context.policyEngine = await loadEnterprisePolicyEngine(configWithTagFilter.policy);
199756
201609
  logger_1.logger.debug(`[PolicyEngine] Initialized: ${context.policyEngine?.constructor?.name || 'unknown'}`);
199757
201610
  }
@@ -210025,7 +211878,7 @@ async function initTelemetry(opts = {}) {
210025
211878
  const path = __nccwpck_require__(16928);
210026
211879
  const outDir = opts.file?.dir ||
210027
211880
  process.env.VISOR_TRACE_DIR ||
210028
- __nccwpck_require__.ab + "traces";
211881
+ path.join(process.cwd(), 'output', 'traces');
210029
211882
  fs.mkdirSync(outDir, { recursive: true });
210030
211883
  const ts = new Date().toISOString().replace(/[:.]/g, '-');
210031
211884
  process.env.VISOR_FALLBACK_TRACE_FILE = path.join(outDir, `run-${ts}.ndjson`);
@@ -210230,7 +212083,7 @@ async function shutdownTelemetry() {
210230
212083
  if (process.env.VISOR_TRACE_REPORT === 'true') {
210231
212084
  const fs = __nccwpck_require__(79896);
210232
212085
  const path = __nccwpck_require__(16928);
210233
- const outDir = process.env.VISOR_TRACE_DIR || __nccwpck_require__.ab + "traces";
212086
+ const outDir = process.env.VISOR_TRACE_DIR || path.join(process.cwd(), 'output', 'traces');
210234
212087
  if (!fs.existsSync(outDir))
210235
212088
  fs.mkdirSync(outDir, { recursive: true });
210236
212089
  const ts = new Date().toISOString().replace(/[:.]/g, '-');
@@ -210729,7 +212582,7 @@ function __getOrCreateNdjsonPath() {
210729
212582
  fs.mkdirSync(dir, { recursive: true });
210730
212583
  return __ndjsonPath;
210731
212584
  }
210732
- const outDir = process.env.VISOR_TRACE_DIR || __nccwpck_require__.ab + "traces";
212585
+ const outDir = process.env.VISOR_TRACE_DIR || path.join(process.cwd(), 'output', 'traces');
210733
212586
  if (!fs.existsSync(outDir))
210734
212587
  fs.mkdirSync(outDir, { recursive: true });
210735
212588
  if (!__ndjsonPath) {
@@ -224465,6 +226318,12 @@ class WorkflowRegistry {
224465
226318
  message: 'Input parameter schema is recommended',
224466
226319
  });
224467
226320
  }
226321
+ if (input.schema?.type === 'array' && !input.schema.items) {
226322
+ warnings.push({
226323
+ path: `inputs[${i}].schema`,
226324
+ message: 'Array schema should define "items" (e.g. items: { type: string }). Some LLM providers (Gemini) reject array schemas without items.',
226325
+ });
226326
+ }
224468
226327
  }
224469
226328
  }
224470
226329
  // Validate output parameters
@@ -224683,22 +226542,6 @@ class WorkflowRegistry {
224683
226542
  exports.WorkflowRegistry = WorkflowRegistry;
224684
226543
 
224685
226544
 
224686
- /***/ }),
224687
-
224688
- /***/ 7065:
224689
- /***/ ((module) => {
224690
-
224691
- module.exports = eval("require")("./enterprise/loader");
224692
-
224693
-
224694
- /***/ }),
224695
-
224696
- /***/ 71370:
224697
- /***/ ((module) => {
224698
-
224699
- module.exports = eval("require")("./enterprise/policy/policy-input-builder");
224700
-
224701
-
224702
226545
  /***/ }),
224703
226546
 
224704
226547
  /***/ 18327:
@@ -355804,9 +357647,10 @@ You are working with a workspace. Available paths: ${workspaceDesc}
355804
357647
  }
355805
357648
  if (completionAttempted && this.completionPrompt && !options._completionPromptProcessed) {
355806
357649
  if (this.debug) {
355807
- console.log("[DEBUG] Running completion prompt for post-completion validation/review...");
357650
+ console.log("[DEBUG] Running completion prompt as continuation of current session...");
355808
357651
  }
355809
357652
  try {
357653
+ const originalResult = finalResult;
355810
357654
  if (this.tracer) {
355811
357655
  this.tracer.recordEvent("completion_prompt.started", {
355812
357656
  "completion_prompt.original_result_length": finalResult?.length || 0
@@ -355819,24 +357663,66 @@ Here is the result to review:
355819
357663
  ${finalResult}
355820
357664
  </result>
355821
357665
 
355822
- After reviewing, provide your final answer using attempt_completion.`;
355823
- const savedOutputItems = this._outputBuffer ? [...this._outputBuffer.items] : [];
355824
- const savedExtractedBlocks = this._extractedRawBlocks ? [...this._extractedRawBlocks] : [];
355825
- const completionResult2 = await this.answer(completionPromptMessage, [], {
355826
- ...options,
355827
- _completionPromptProcessed: true
355828
- });
355829
- if (this._outputBuffer) {
355830
- this._outputBuffer.items = savedOutputItems;
357666
+ Double-check your response based on the criteria above. If everything looks good, respond with your previous answer exactly as-is using attempt_completion. If something needs to be fixed or is missing, do it now, then respond with the COMPLETE updated answer (everything you did in total, not just the fix) using attempt_completion.`;
357667
+ currentMessages.push({ role: "user", content: completionPromptMessage });
357668
+ completionResult = null;
357669
+ completionAttempted = false;
357670
+ const completionMaxIterations = 5;
357671
+ const completionStreamOptions = {
357672
+ model: this.provider ? this.provider(this.model) : this.model,
357673
+ messages: this.prepareMessagesWithImages(currentMessages),
357674
+ tools: tools2,
357675
+ stopWhen: (0, import_ai4.stepCountIs)(completionMaxIterations),
357676
+ maxTokens: maxResponseTokens,
357677
+ temperature: 0.3,
357678
+ onStepFinish: ({ toolResults, text, finishReason, usage }) => {
357679
+ if (usage) {
357680
+ this.tokenCounter.recordUsage(usage);
357681
+ }
357682
+ if (options.onStream && text) {
357683
+ options.onStream(text);
357684
+ }
357685
+ if (this.debug) {
357686
+ console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
357687
+ }
357688
+ }
357689
+ };
357690
+ const providerOpts = this._buildThinkingProviderOptions(maxResponseTokens);
357691
+ if (providerOpts) {
357692
+ completionStreamOptions.providerOptions = providerOpts;
357693
+ }
357694
+ const cpResult = await this.streamTextWithRetryAndFallback(completionStreamOptions);
357695
+ const cpFinalText = await cpResult.text;
357696
+ const cpUsage = await cpResult.usage;
357697
+ if (cpUsage) {
357698
+ this.tokenCounter.recordUsage(cpUsage, cpResult.experimental_providerMetadata);
357699
+ }
357700
+ const cpMessages = await cpResult.response?.messages;
357701
+ if (cpMessages) {
357702
+ for (const msg of cpMessages) {
357703
+ currentMessages.push(msg);
357704
+ }
357705
+ }
357706
+ if (completionResult) {
357707
+ finalResult = completionResult;
357708
+ completionAttempted = true;
357709
+ } else if (cpFinalText && cpFinalText.trim().length > 0) {
357710
+ finalResult = cpFinalText;
357711
+ completionAttempted = true;
357712
+ } else {
357713
+ finalResult = originalResult;
357714
+ completionAttempted = true;
357715
+ if (this.debug) {
357716
+ console.log("[DEBUG] Completion prompt returned empty result, keeping original.");
357717
+ }
355831
357718
  }
355832
- this._extractedRawBlocks = savedExtractedBlocks;
355833
- finalResult = completionResult2;
355834
357719
  if (this.debug) {
355835
- console.log(`[DEBUG] Completion prompt finished. New result length: ${finalResult?.length || 0}`);
357720
+ console.log(`[DEBUG] Completion prompt finished. Final result length: ${finalResult?.length || 0}`);
355836
357721
  }
355837
357722
  if (this.tracer) {
355838
357723
  this.tracer.recordEvent("completion_prompt.completed", {
355839
- "completion_prompt.final_result_length": finalResult?.length || 0
357724
+ "completion_prompt.final_result_length": finalResult?.length || 0,
357725
+ "completion_prompt.used_original": finalResult === originalResult
355840
357726
  });
355841
357727
  }
355842
357728
  } catch (error2) {
@@ -357594,6 +359480,17 @@ function parseDelegatedTargets(rawResponse) {
357594
359480
  }
357595
359481
  return normalizeTargets(fallbackTargetsFromText(trimmed));
357596
359482
  }
359483
+ function splitTargetSuffix(target) {
359484
+ const searchStart = target.length > 2 && target[1] === ":" && /[a-zA-Z]/.test(target[0]) ? 2 : 0;
359485
+ const colonIdx = target.indexOf(":", searchStart);
359486
+ const hashIdx = target.indexOf("#");
359487
+ if (colonIdx !== -1 && (hashIdx === -1 || colonIdx < hashIdx)) {
359488
+ return { filePart: target.substring(0, colonIdx), suffix: target.substring(colonIdx) };
359489
+ } else if (hashIdx !== -1) {
359490
+ return { filePart: target.substring(0, hashIdx), suffix: target.substring(hashIdx) };
359491
+ }
359492
+ return { filePart: target, suffix: "" };
359493
+ }
357597
359494
  function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, allowTests }) {
357598
359495
  return [
357599
359496
  "You are a code-search subagent. Your job is to find ALL relevant code locations for the given query.",
@@ -357622,7 +359519,7 @@ function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, all
357622
359519
  "Deduplicate targets. Do NOT explain or answer - ONLY return the JSON targets."
357623
359520
  ].join("\n");
357624
359521
  }
357625
- var import_ai5, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool;
359522
+ var import_ai5, import_fs11, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool;
357626
359523
  var init_vercel = __esm({
357627
359524
  "src/tools/vercel.js"() {
357628
359525
  "use strict";
@@ -357633,6 +359530,7 @@ var init_vercel = __esm({
357633
359530
  init_delegate();
357634
359531
  init_analyzeAll();
357635
359532
  init_common2();
359533
+ import_fs11 = __nccwpck_require__(79896);
357636
359534
  init_error_types();
357637
359535
  init_hashline();
357638
359536
  CODE_SEARCH_SCHEMA = {
@@ -357758,10 +359656,47 @@ var init_vercel = __esm({
357758
359656
  }
357759
359657
  return fallbackResult;
357760
359658
  }
359659
+ const delegateBase = options.allowedFolders?.[0] || options.cwd || ".";
357761
359660
  const resolutionBase = searchPaths[0] || options.cwd || ".";
357762
- const resolvedTargets = targets.map((target) => resolveTargetPath(target, resolutionBase));
359661
+ const resolvedTargets = targets.map((target) => resolveTargetPath(target, delegateBase));
359662
+ const validatedTargets = [];
359663
+ for (const target of resolvedTargets) {
359664
+ const { filePart, suffix } = splitTargetSuffix(target);
359665
+ if ((0, import_fs11.existsSync)(filePart)) {
359666
+ validatedTargets.push(target);
359667
+ continue;
359668
+ }
359669
+ let fixed = false;
359670
+ const parts = filePart.split("/").filter(Boolean);
359671
+ for (let i5 = 0; i5 < parts.length - 1; i5++) {
359672
+ if (parts[i5] === parts[i5 + 1]) {
359673
+ const candidate = "/" + [...parts.slice(0, i5), ...parts.slice(i5 + 1)].join("/");
359674
+ if ((0, import_fs11.existsSync)(candidate)) {
359675
+ validatedTargets.push(candidate + suffix);
359676
+ if (debug) console.error(`[search-delegate] Fixed doubled path segment: ${filePart} \u2192 ${candidate}`);
359677
+ fixed = true;
359678
+ break;
359679
+ }
359680
+ }
359681
+ }
359682
+ if (fixed) continue;
359683
+ for (const altBase of [resolutionBase, options.cwd].filter(Boolean)) {
359684
+ if (altBase === delegateBase) continue;
359685
+ const altResolved = resolveTargetPath(target, altBase);
359686
+ const { filePart: altFile } = splitTargetSuffix(altResolved);
359687
+ if ((0, import_fs11.existsSync)(altFile)) {
359688
+ validatedTargets.push(altResolved);
359689
+ if (debug) console.error(`[search-delegate] Resolved with alt base: ${filePart} \u2192 ${altFile}`);
359690
+ fixed = true;
359691
+ break;
359692
+ }
359693
+ }
359694
+ if (fixed) continue;
359695
+ if (debug) console.error(`[search-delegate] Warning: target may not exist: ${filePart}`);
359696
+ validatedTargets.push(target);
359697
+ }
357763
359698
  const extractOptions = {
357764
- files: resolvedTargets,
359699
+ files: validatedTargets,
357765
359700
  cwd: resolutionBase,
357766
359701
  allowTests: allow_tests ?? true
357767
359702
  };
@@ -358314,7 +360249,7 @@ Example: <edit><file_path>${file_path}</file_path><symbol>${allMatches[0].qualif
358314
360249
  Example: <extract><targets>${file_path}#${symbol15}</targets></extract>`;
358315
360250
  }
358316
360251
  }
358317
- const content = await import_fs11.promises.readFile(resolvedPath2, "utf-8");
360252
+ const content = await import_fs12.promises.readFile(resolvedPath2, "utf-8");
358318
360253
  const lines = content.split("\n");
358319
360254
  if (position) {
358320
360255
  const refIndent = detectBaseIndent(symbolInfo.code);
@@ -358325,7 +360260,7 @@ Example: <extract><targets>${file_path}#${symbol15}</targets></extract>`;
358325
360260
  } else {
358326
360261
  lines.splice(symbolInfo.startLine - 1, 0, ...newLines, "");
358327
360262
  }
358328
- await import_fs11.promises.writeFile(resolvedPath2, lines.join("\n"), "utf-8");
360263
+ await import_fs12.promises.writeFile(resolvedPath2, lines.join("\n"), "utf-8");
358329
360264
  if (fileTracker) {
358330
360265
  const updated = await findSymbol(resolvedPath2, symbol15, cwd || process.cwd());
358331
360266
  if (updated) {
@@ -358343,7 +360278,7 @@ Example: <extract><targets>${file_path}#${symbol15}</targets></extract>`;
358343
360278
  const reindented = reindent(new_string, originalIndent);
358344
360279
  const newLines = reindented.split("\n");
358345
360280
  lines.splice(symbolInfo.startLine - 1, symbolInfo.endLine - symbolInfo.startLine + 1, ...newLines);
358346
- await import_fs11.promises.writeFile(resolvedPath2, lines.join("\n"), "utf-8");
360281
+ await import_fs12.promises.writeFile(resolvedPath2, lines.join("\n"), "utf-8");
358347
360282
  if (fileTracker) {
358348
360283
  const updated = await findSymbol(resolvedPath2, symbol15, cwd || process.cwd());
358349
360284
  if (updated) {
@@ -358398,7 +360333,7 @@ async function handleLineEdit({ resolvedPath: resolvedPath2, file_path, start_li
358398
360333
  if (position !== void 0 && position !== null && position !== "before" && position !== "after") {
358399
360334
  return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before the line, or position="after" to insert after it.';
358400
360335
  }
358401
- const content = await import_fs11.promises.readFile(resolvedPath2, "utf-8");
360336
+ const content = await import_fs12.promises.readFile(resolvedPath2, "utf-8");
358402
360337
  const fileLines = content.split("\n");
358403
360338
  if (startLine > fileLines.length) {
358404
360339
  return `Error editing file: Line ${startLine} is beyond file length (${fileLines.length} lines). Use 'extract' to read the current file content.`;
@@ -358427,20 +360362,20 @@ async function handleLineEdit({ resolvedPath: resolvedPath2, file_path, start_li
358427
360362
  const newLines = cleaned === "" ? [] : cleaned.split("\n");
358428
360363
  if (position === "after") {
358429
360364
  fileLines.splice(startLine, 0, ...newLines);
358430
- await import_fs11.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
360365
+ await import_fs12.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
358431
360366
  if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath2);
358432
360367
  const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted after line ${startLine}`;
358433
360368
  return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine, action, modifications);
358434
360369
  } else if (position === "before") {
358435
360370
  fileLines.splice(startLine - 1, 0, ...newLines);
358436
- await import_fs11.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
360371
+ await import_fs12.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
358437
360372
  if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath2);
358438
360373
  const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted before line ${startLine}`;
358439
360374
  return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine - 1, action, modifications);
358440
360375
  } else {
358441
360376
  const replacedCount = endLine - startLine + 1;
358442
360377
  fileLines.splice(startLine - 1, replacedCount, ...newLines);
358443
- await import_fs11.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
360378
+ await import_fs12.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
358444
360379
  if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath2);
358445
360380
  let action;
358446
360381
  if (newLines.length === 0) {
@@ -358453,14 +360388,14 @@ async function handleLineEdit({ resolvedPath: resolvedPath2, file_path, start_li
358453
360388
  return buildLineEditResponse(file_path, startLine, endLine, newLines.length, fileLines, startLine - 1, action, modifications);
358454
360389
  }
358455
360390
  }
358456
- var import_ai6, import_fs11, import_path16, import_fs12, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
360391
+ var import_ai6, import_fs12, import_path16, import_fs13, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
358457
360392
  var init_edit = __esm({
358458
360393
  "src/tools/edit.js"() {
358459
360394
  "use strict";
358460
360395
  import_ai6 = __nccwpck_require__(86619);
358461
- import_fs11 = __nccwpck_require__(79896);
358462
- import_path16 = __nccwpck_require__(16928);
358463
360396
  import_fs12 = __nccwpck_require__(79896);
360397
+ import_path16 = __nccwpck_require__(16928);
360398
+ import_fs13 = __nccwpck_require__(79896);
358464
360399
  init_path_validation();
358465
360400
  init_fuzzyMatch();
358466
360401
  init_symbolEdit();
@@ -358544,7 +360479,7 @@ Parameters:
358544
360479
  const relativePath = toRelativePath(resolvedPath2, workspaceRoot);
358545
360480
  return `Error editing file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
358546
360481
  }
358547
- if (!(0, import_fs12.existsSync)(resolvedPath2)) {
360482
+ if (!(0, import_fs13.existsSync)(resolvedPath2)) {
358548
360483
  return `Error editing file: File not found - ${file_path}. Verify the path is correct and the file exists. Use 'search' to find files by name, or 'create' to make a new file.`;
358549
360484
  }
358550
360485
  if (options.fileTracker && !options.fileTracker.isFileSeen(resolvedPath2)) {
@@ -358574,7 +360509,7 @@ Example: <extract><targets>${displayPath}</targets></extract>`;
358574
360509
  Example: <extract><targets>${displayPath}</targets></extract>`;
358575
360510
  }
358576
360511
  }
358577
- const content = await import_fs11.promises.readFile(resolvedPath2, "utf-8");
360512
+ const content = await import_fs12.promises.readFile(resolvedPath2, "utf-8");
358578
360513
  let matchTarget = old_string;
358579
360514
  let matchStrategy = "exact";
358580
360515
  if (!content.includes(old_string)) {
@@ -358606,7 +360541,7 @@ Example: <extract><targets>${displayPath}</targets></extract>`;
358606
360541
  if (newContent === content) {
358607
360542
  return `Error editing file: No changes made - the replacement result is identical to the original. Verify that old_string and new_string are actually different. If fuzzy matching was used, the matched text may already equal new_string.`;
358608
360543
  }
358609
- await import_fs11.promises.writeFile(resolvedPath2, newContent, "utf-8");
360544
+ await import_fs12.promises.writeFile(resolvedPath2, newContent, "utf-8");
358610
360545
  if (options.fileTracker) {
358611
360546
  await options.fileTracker.trackFileAfterWrite(resolvedPath2);
358612
360547
  options.fileTracker.recordTextEdit(resolvedPath2);
@@ -358677,13 +360612,13 @@ Important:
358677
360612
  const relativePath = toRelativePath(resolvedPath2, workspaceRoot);
358678
360613
  return `Error creating file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
358679
360614
  }
358680
- if ((0, import_fs12.existsSync)(resolvedPath2) && !overwrite) {
360615
+ if ((0, import_fs13.existsSync)(resolvedPath2) && !overwrite) {
358681
360616
  return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
358682
360617
  }
358683
- const existed = (0, import_fs12.existsSync)(resolvedPath2);
360618
+ const existed = (0, import_fs13.existsSync)(resolvedPath2);
358684
360619
  const dir = (0, import_path16.dirname)(resolvedPath2);
358685
- await import_fs11.promises.mkdir(dir, { recursive: true });
358686
- await import_fs11.promises.writeFile(resolvedPath2, content, "utf-8");
360620
+ await import_fs12.promises.mkdir(dir, { recursive: true });
360621
+ await import_fs12.promises.writeFile(resolvedPath2, content, "utf-8");
358687
360622
  if (options.fileTracker) await options.fileTracker.trackFileAfterWrite(resolvedPath2);
358688
360623
  const action = existed && overwrite ? "overwrote" : "created";
358689
360624
  const bytes = Buffer.byteLength(content, "utf-8");
@@ -359325,10 +361260,10 @@ async function listFilesByLevel(options) {
359325
361260
  maxFiles = 100,
359326
361261
  respectGitignore = true
359327
361262
  } = options;
359328
- if (!import_fs13.default.existsSync(directory)) {
361263
+ if (!import_fs14.default.existsSync(directory)) {
359329
361264
  throw new Error(`Directory does not exist: ${directory}`);
359330
361265
  }
359331
- const gitDirExists = import_fs13.default.existsSync(import_path17.default.join(directory, ".git"));
361266
+ const gitDirExists = import_fs14.default.existsSync(import_path17.default.join(directory, ".git"));
359332
361267
  if (gitDirExists && respectGitignore) {
359333
361268
  try {
359334
361269
  return await listFilesUsingGit(directory, maxFiles);
@@ -359359,7 +361294,7 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
359359
361294
  while (queue.length > 0 && result.length < maxFiles) {
359360
361295
  const { dir, level } = queue.shift();
359361
361296
  try {
359362
- const entries = import_fs13.default.readdirSync(dir, { withFileTypes: true });
361297
+ const entries = import_fs14.default.readdirSync(dir, { withFileTypes: true });
359363
361298
  const files = entries.filter((entry) => {
359364
361299
  const fullPath = import_path17.default.join(dir, entry.name);
359365
361300
  return getEntryTypeSync(entry, fullPath).isFile;
@@ -359390,11 +361325,11 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
359390
361325
  }
359391
361326
  function loadGitignorePatterns(directory) {
359392
361327
  const gitignorePath = import_path17.default.join(directory, ".gitignore");
359393
- if (!import_fs13.default.existsSync(gitignorePath)) {
361328
+ if (!import_fs14.default.existsSync(gitignorePath)) {
359394
361329
  return [];
359395
361330
  }
359396
361331
  try {
359397
- const content = import_fs13.default.readFileSync(gitignorePath, "utf8");
361332
+ const content = import_fs14.default.readFileSync(gitignorePath, "utf8");
359398
361333
  return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
359399
361334
  } catch (error2) {
359400
361335
  console.error(`Warning: Could not read .gitignore: ${error2.message}`);
@@ -359412,11 +361347,11 @@ function shouldIgnore(filePath, ignorePatterns) {
359412
361347
  }
359413
361348
  return false;
359414
361349
  }
359415
- var import_fs13, import_path17, import_util12, import_child_process10, execAsync3;
361350
+ var import_fs14, import_path17, import_util12, import_child_process10, execAsync3;
359416
361351
  var init_file_lister = __esm({
359417
361352
  "src/utils/file-lister.js"() {
359418
361353
  "use strict";
359419
- import_fs13 = __toESM(__nccwpck_require__(79896), 1);
361354
+ import_fs14 = __toESM(__nccwpck_require__(79896), 1);
359420
361355
  import_path17 = __toESM(__nccwpck_require__(16928), 1);
359421
361356
  import_util12 = __nccwpck_require__(39023);
359422
361357
  import_child_process10 = __nccwpck_require__(35317);
@@ -359435,11 +361370,11 @@ function initializeSimpleTelemetryFromOptions(options) {
359435
361370
  });
359436
361371
  return telemetry;
359437
361372
  }
359438
- var import_fs14, import_path18, SimpleTelemetry, SimpleAppTracer;
361373
+ var import_fs15, import_path18, SimpleTelemetry, SimpleAppTracer;
359439
361374
  var init_simpleTelemetry = __esm({
359440
361375
  "src/agent/simpleTelemetry.js"() {
359441
361376
  "use strict";
359442
- import_fs14 = __nccwpck_require__(79896);
361377
+ import_fs15 = __nccwpck_require__(79896);
359443
361378
  import_path18 = __nccwpck_require__(16928);
359444
361379
  SimpleTelemetry = class {
359445
361380
  constructor(options = {}) {
@@ -359455,10 +361390,10 @@ var init_simpleTelemetry = __esm({
359455
361390
  initializeFileExporter() {
359456
361391
  try {
359457
361392
  const dir = (0, import_path18.dirname)(this.filePath);
359458
- if (!(0, import_fs14.existsSync)(dir)) {
359459
- (0, import_fs14.mkdirSync)(dir, { recursive: true });
361393
+ if (!(0, import_fs15.existsSync)(dir)) {
361394
+ (0, import_fs15.mkdirSync)(dir, { recursive: true });
359460
361395
  }
359461
- this.stream = (0, import_fs14.createWriteStream)(this.filePath, { flags: "a" });
361396
+ this.stream = (0, import_fs15.createWriteStream)(this.filePath, { flags: "a" });
359462
361397
  this.stream.on("error", (error2) => {
359463
361398
  console.error(`[SimpleTelemetry] Stream error: ${error2.message}`);
359464
361399
  });
@@ -395235,7 +397170,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"100":"Continue","101":"Switching Pro
395235
397170
  /***/ ((module) => {
395236
397171
 
395237
397172
  "use strict";
395238
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.153","main":"dist/index.js","bin":{"visor":"./dist/index.js"},"exports":{".":{"require":"./dist/index.js","import":"./dist/index.js"},"./sdk":{"types":"./dist/sdk/sdk.d.ts","import":"./dist/sdk/sdk.mjs","require":"./dist/sdk/sdk.js"},"./cli":{"require":"./dist/index.js"}},"files":["dist/","defaults/","action.yml","README.md","LICENSE"],"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"build:cli":"ncc build src/index.ts -o dist && cp -r defaults dist/ && cp -r output dist/ && cp -r docs dist/ && cp -r examples dist/ && cp -r src/debug-visualizer/ui dist/debug-visualizer/ && node scripts/inject-version.js && echo \'#!/usr/bin/env node\' | cat - dist/index.js > temp && mv temp dist/index.js && chmod +x dist/index.js","build:sdk":"tsup src/sdk.ts --dts --sourcemap --format esm,cjs --out-dir dist/sdk","build":"./scripts/build-oss.sh","build:ee":"npm run build:cli && npm run build:sdk","test":"jest && npm run test:yaml","test:unit":"jest","prepublishOnly":"npm run build","test:watch":"jest --watch","test:coverage":"jest --coverage","test:ee":"jest --testPathPatterns=\'tests/ee\' --testPathIgnorePatterns=\'/node_modules/\' --no-coverage","test:manual:bash":"RUN_MANUAL_TESTS=true jest tests/manual/bash-config-manual.test.ts","lint":"eslint src tests --ext .ts","lint:fix":"eslint src tests --ext .ts --fix","format":"prettier --write src tests","format:check":"prettier --check src tests","clean":"","clean:traces":"node scripts/clean-traces.js","prebuild":"npm run clean && node scripts/generate-config-schema.js","pretest":"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli","pretest:unit":"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli","test:with-build":"npm run build:cli && jest","test:yaml":"node dist/index.js test --progress compact","test:yaml:parallel":"node dist/index.js test --progress compact --max-parallel 4","prepare":"husky","pre-commit":"lint-staged","deploy:site":"cd site && npx wrangler pages deploy . --project-name=visor-site --commit-dirty=true","deploy:worker":"npx wrangler deploy","deploy":"npm run deploy:site && npm run deploy:worker","publish:ee":"./scripts/publish-ee.sh","release":"./scripts/release.sh","release:patch":"./scripts/release.sh patch","release:minor":"./scripts/release.sh minor","release:major":"./scripts/release.sh major","release:prerelease":"./scripts/release.sh prerelease","docs:validate":"node scripts/validate-readme-links.js","workshop:setup":"npm install -D reveal-md@6.1.2","workshop:serve":"cd workshop && reveal-md slides.md -w","workshop:export":"reveal-md workshop/slides.md --static workshop/build","workshop:pdf":"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter","workshop:pdf:ci":"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter --puppeteer-launch-args=\\"--no-sandbox --disable-dev-shm-usage\\"","workshop:pdf:a4":"reveal-md workshop/slides.md --print workshop/Visor-Workshop-A4.pdf --print-size A4","workshop:build":"npm run workshop:export && npm run workshop:pdf","simulate:issue":"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issues --action opened --debug","simulate:comment":"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issue_comment --action created --debug"},"keywords":["code-review","ai","github-action","cli","pr-review","visor"],"author":"Probe Labs","license":"MIT","description":"AI workflow engine for code review, assistants, and automation — orchestrate checks, MCP tools, and AI providers with YAML-driven pipelines","repository":{"type":"git","url":"git+https://github.com/probelabs/visor.git"},"bugs":{"url":"https://github.com/probelabs/visor/issues"},"homepage":"https://github.com/probelabs/visor#readme","dependencies":{"@actions/core":"^1.11.1","@apidevtools/swagger-parser":"^12.1.0","@modelcontextprotocol/sdk":"^1.25.3","@nyariv/sandboxjs":"github:probelabs/SandboxJS#f1c13b8eee98734a8ea024061eada4aa9a9ff2e9","@octokit/action":"^8.0.2","@octokit/auth-app":"^8.1.0","@octokit/core":"^7.0.3","@octokit/rest":"^22.0.0","@opentelemetry/api":"^1.9.0","@opentelemetry/core":"^1.30.1","@opentelemetry/exporter-trace-otlp-grpc":"^0.203.0","@opentelemetry/exporter-trace-otlp-http":"^0.203.0","@opentelemetry/instrumentation":"^0.203.0","@opentelemetry/resources":"^1.30.1","@opentelemetry/sdk-metrics":"^1.30.1","@opentelemetry/sdk-node":"^0.203.0","@opentelemetry/sdk-trace-base":"^1.30.1","@opentelemetry/semantic-conventions":"^1.30.1","@probelabs/probe":"^0.6.0-rc269","@types/commander":"^2.12.0","@types/uuid":"^10.0.0","acorn":"^8.16.0","acorn-walk":"^8.3.5","ajv":"^8.17.1","ajv-formats":"^3.0.1","better-sqlite3":"^11.0.0","blessed":"^0.1.81","cli-table3":"^0.6.5","commander":"^14.0.0","deepmerge":"^4.3.1","dotenv":"^17.2.3","ignore":"^7.0.5","js-yaml":"^4.1.0","jsonpath-plus":"^10.4.0","liquidjs":"^10.21.1","minimatch":"^10.2.2","node-cron":"^3.0.3","open":"^9.1.0","simple-git":"^3.28.0","uuid":"^11.1.0","ws":"^8.18.3"},"optionalDependencies":{"@anthropic/claude-code-sdk":"npm:null@*","@open-policy-agent/opa-wasm":"^1.10.0","knex":"^3.1.0","mysql2":"^3.11.0","pg":"^8.13.0","tedious":"^19.0.0"},"devDependencies":{"@eslint/js":"^9.34.0","@kie/act-js":"^2.6.2","@kie/mock-github":"^2.0.1","@swc/core":"^1.13.2","@swc/jest":"^0.2.37","@types/better-sqlite3":"^7.6.0","@types/blessed":"^0.1.27","@types/jest":"^30.0.0","@types/js-yaml":"^4.0.9","@types/node":"^24.3.0","@types/node-cron":"^3.0.11","@types/ws":"^8.18.1","@typescript-eslint/eslint-plugin":"^8.42.0","@typescript-eslint/parser":"^8.42.0","@vercel/ncc":"^0.38.4","eslint":"^9.34.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4","husky":"^9.1.7","jest":"^30.1.3","lint-staged":"^16.1.6","prettier":"^3.6.2","reveal-md":"^6.1.2","ts-json-schema-generator":"^1.5.1","ts-node":"^10.9.2","tsup":"^8.5.0","typescript":"^5.9.2","wrangler":"^3.0.0"},"peerDependenciesMeta":{"@anthropic/claude-code-sdk":{"optional":true}},"directories":{"test":"tests"},"lint-staged":{"src/**/*.{ts,js}":["eslint --fix","prettier --write"],"tests/**/*.{ts,js}":["eslint --fix","prettier --write"],"*.{json,md,yml,yaml}":["prettier --write"]}}');
397173
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.42","main":"dist/index.js","bin":{"visor":"./dist/index.js"},"exports":{".":{"require":"./dist/index.js","import":"./dist/index.js"},"./sdk":{"types":"./dist/sdk/sdk.d.ts","import":"./dist/sdk/sdk.mjs","require":"./dist/sdk/sdk.js"},"./cli":{"require":"./dist/index.js"}},"files":["dist/","defaults/","action.yml","README.md","LICENSE"],"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"build:cli":"ncc build src/index.ts -o dist && cp -r defaults dist/ && cp -r output dist/ && cp -r docs dist/ && cp -r examples dist/ && cp -r src/debug-visualizer/ui dist/debug-visualizer/ && node scripts/inject-version.js && echo \'#!/usr/bin/env node\' | cat - dist/index.js > temp && mv temp dist/index.js && chmod +x dist/index.js","build:sdk":"tsup src/sdk.ts --dts --sourcemap --format esm,cjs --out-dir dist/sdk","build":"./scripts/build-oss.sh","build:ee":"npm run build:cli && npm run build:sdk","test":"jest && npm run test:yaml","test:unit":"jest","prepublishOnly":"npm run build","test:watch":"jest --watch","test:coverage":"jest --coverage","test:ee":"jest --testPathPatterns=\'tests/ee\' --testPathIgnorePatterns=\'/node_modules/\' --no-coverage","test:manual:bash":"RUN_MANUAL_TESTS=true jest tests/manual/bash-config-manual.test.ts","lint":"eslint src tests --ext .ts","lint:fix":"eslint src tests --ext .ts --fix","format":"prettier --write src tests","format:check":"prettier --check src tests","clean":"","clean:traces":"node scripts/clean-traces.js","prebuild":"npm run clean && node scripts/generate-config-schema.js","pretest":"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli","pretest:unit":"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli","test:with-build":"npm run build:cli && jest","test:yaml":"node dist/index.js test --progress compact","test:yaml:parallel":"node dist/index.js test --progress compact --max-parallel 4","prepare":"husky","pre-commit":"lint-staged","deploy:site":"cd site && npx wrangler pages deploy . --project-name=visor-site --commit-dirty=true","deploy:worker":"npx wrangler deploy","deploy":"npm run deploy:site && npm run deploy:worker","publish:ee":"./scripts/publish-ee.sh","release":"./scripts/release.sh","release:patch":"./scripts/release.sh patch","release:minor":"./scripts/release.sh minor","release:major":"./scripts/release.sh major","release:prerelease":"./scripts/release.sh prerelease","docs:validate":"node scripts/validate-readme-links.js","workshop:setup":"npm install -D reveal-md@6.1.2","workshop:serve":"cd workshop && reveal-md slides.md -w","workshop:export":"reveal-md workshop/slides.md --static workshop/build","workshop:pdf":"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter","workshop:pdf:ci":"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter --puppeteer-launch-args=\\"--no-sandbox --disable-dev-shm-usage\\"","workshop:pdf:a4":"reveal-md workshop/slides.md --print workshop/Visor-Workshop-A4.pdf --print-size A4","workshop:build":"npm run workshop:export && npm run workshop:pdf","simulate:issue":"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issues --action opened --debug","simulate:comment":"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issue_comment --action created --debug"},"keywords":["code-review","ai","github-action","cli","pr-review","visor"],"author":"Probe Labs","license":"MIT","description":"AI workflow engine for code review, assistants, and automation — orchestrate checks, MCP tools, and AI providers with YAML-driven pipelines","repository":{"type":"git","url":"git+https://github.com/probelabs/visor.git"},"bugs":{"url":"https://github.com/probelabs/visor/issues"},"homepage":"https://github.com/probelabs/visor#readme","dependencies":{"@actions/core":"^1.11.1","@apidevtools/swagger-parser":"^12.1.0","@modelcontextprotocol/sdk":"^1.25.3","@nyariv/sandboxjs":"github:probelabs/SandboxJS#f1c13b8eee98734a8ea024061eada4aa9a9ff2e9","@octokit/action":"^8.0.2","@octokit/auth-app":"^8.1.0","@octokit/core":"^7.0.3","@octokit/rest":"^22.0.0","@opentelemetry/api":"^1.9.0","@opentelemetry/core":"^1.30.1","@opentelemetry/exporter-trace-otlp-grpc":"^0.203.0","@opentelemetry/exporter-trace-otlp-http":"^0.203.0","@opentelemetry/instrumentation":"^0.203.0","@opentelemetry/resources":"^1.30.1","@opentelemetry/sdk-metrics":"^1.30.1","@opentelemetry/sdk-node":"^0.203.0","@opentelemetry/sdk-trace-base":"^1.30.1","@opentelemetry/semantic-conventions":"^1.30.1","@probelabs/probe":"^0.6.0-rc271","@types/commander":"^2.12.0","@types/uuid":"^10.0.0","acorn":"^8.16.0","acorn-walk":"^8.3.5","ajv":"^8.17.1","ajv-formats":"^3.0.1","better-sqlite3":"^11.0.0","blessed":"^0.1.81","cli-table3":"^0.6.5","commander":"^14.0.0","deepmerge":"^4.3.1","dotenv":"^17.2.3","ignore":"^7.0.5","js-yaml":"^4.1.0","jsonpath-plus":"^10.4.0","liquidjs":"^10.21.1","minimatch":"^10.2.2","node-cron":"^3.0.3","open":"^9.1.0","simple-git":"^3.28.0","uuid":"^11.1.0","ws":"^8.18.3"},"optionalDependencies":{"@anthropic/claude-code-sdk":"npm:null@*","@open-policy-agent/opa-wasm":"^1.10.0","knex":"^3.1.0","mysql2":"^3.11.0","pg":"^8.13.0","tedious":"^19.0.0"},"devDependencies":{"@eslint/js":"^9.34.0","@kie/act-js":"^2.6.2","@kie/mock-github":"^2.0.1","@swc/core":"^1.13.2","@swc/jest":"^0.2.37","@types/better-sqlite3":"^7.6.0","@types/blessed":"^0.1.27","@types/jest":"^30.0.0","@types/js-yaml":"^4.0.9","@types/node":"^24.3.0","@types/node-cron":"^3.0.11","@types/ws":"^8.18.1","@typescript-eslint/eslint-plugin":"^8.42.0","@typescript-eslint/parser":"^8.42.0","@vercel/ncc":"^0.38.4","eslint":"^9.34.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4","husky":"^9.1.7","jest":"^30.1.3","lint-staged":"^16.1.6","prettier":"^3.6.2","reveal-md":"^6.1.2","ts-json-schema-generator":"^1.5.1","ts-node":"^10.9.2","tsup":"^8.5.0","typescript":"^5.9.2","wrangler":"^3.0.0"},"peerDependenciesMeta":{"@anthropic/claude-code-sdk":{"optional":true}},"directories":{"test":"tests"},"lint-staged":{"src/**/*.{ts,js}":["eslint --fix","prettier --write"],"tests/**/*.{ts,js}":["eslint --fix","prettier --write"],"*.{json,md,yml,yaml}":["prettier --write"]}}');
395239
397174
 
395240
397175
  /***/ })
395241
397176