@probelabs/visor 0.1.144 → 0.1.145

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 (97) hide show
  1. package/dist/config.d.ts.map +1 -1
  2. package/dist/docs/architecture.md +28 -0
  3. package/dist/docs/configuration.md +2 -0
  4. package/dist/docs/sandbox-engines.md +357 -0
  5. package/dist/docs/security.md +40 -0
  6. package/dist/generated/config-schema.d.ts +5 -0
  7. package/dist/generated/config-schema.d.ts.map +1 -1
  8. package/dist/generated/config-schema.json +9 -0
  9. package/dist/index.js +670 -162
  10. package/dist/output/traces/{run-2026-02-25T17-29-59-894Z.ndjson → run-2026-02-26T07-47-34-788Z.ndjson} +84 -84
  11. package/dist/{traces/run-2026-02-25T17-30-47-149Z.ndjson → output/traces/run-2026-02-26T07-48-25-935Z.ndjson} +1118 -1118
  12. package/dist/providers/mcp-check-provider.d.ts.map +1 -1
  13. package/dist/sandbox/bubblewrap-sandbox.d.ts +30 -0
  14. package/dist/sandbox/bubblewrap-sandbox.d.ts.map +1 -0
  15. package/dist/sandbox/index.d.ts +3 -1
  16. package/dist/sandbox/index.d.ts.map +1 -1
  17. package/dist/sandbox/sandbox-manager.d.ts +3 -2
  18. package/dist/sandbox/sandbox-manager.d.ts.map +1 -1
  19. package/dist/sandbox/seatbelt-sandbox.d.ts +36 -0
  20. package/dist/sandbox/seatbelt-sandbox.d.ts.map +1 -0
  21. package/dist/sandbox/types.d.ts +3 -1
  22. package/dist/sandbox/types.d.ts.map +1 -1
  23. package/dist/sdk/{check-provider-registry-VTNNTMWC.mjs → check-provider-registry-HFPKHYTG.mjs} +3 -3
  24. package/dist/sdk/{check-provider-registry-WBEOZCGW.mjs → check-provider-registry-HK6M4PDQ.mjs} +6 -6
  25. package/dist/sdk/{check-provider-registry-GKLK3I2X.mjs → check-provider-registry-TG5G2TF3.mjs} +6 -6
  26. package/dist/sdk/{chunk-D3UC5KUJ.mjs → chunk-5FXGIBJQ.mjs} +467 -100
  27. package/dist/sdk/chunk-5FXGIBJQ.mjs.map +1 -0
  28. package/dist/sdk/{chunk-FG6THKK7.mjs → chunk-6XPTQBXL.mjs} +3 -3
  29. package/dist/sdk/{chunk-FG6THKK7.mjs.map → chunk-6XPTQBXL.mjs.map} +1 -1
  30. package/dist/sdk/{chunk-N7LW3Q5B.mjs → chunk-E6SMU2Z4.mjs} +467 -100
  31. package/dist/sdk/chunk-E6SMU2Z4.mjs.map +1 -0
  32. package/dist/sdk/{chunk-PXWWPPNF.mjs → chunk-GZMQPC6D.mjs} +459 -92
  33. package/dist/sdk/chunk-GZMQPC6D.mjs.map +1 -0
  34. package/dist/sdk/{chunk-CLQTOZKH.mjs → chunk-I42ZCVA5.mjs} +3 -3
  35. package/dist/sdk/chunk-K3M5YVEU.mjs +1502 -0
  36. package/dist/sdk/chunk-K3M5YVEU.mjs.map +1 -0
  37. package/dist/sdk/{chunk-PQWAAGUP.mjs → chunk-L3XPYQ6I.mjs} +2 -2
  38. package/dist/sdk/chunk-L6ABOJVL.mjs +739 -0
  39. package/dist/sdk/chunk-L6ABOJVL.mjs.map +1 -0
  40. package/dist/sdk/chunk-OM3WYVFI.mjs +443 -0
  41. package/dist/sdk/chunk-OM3WYVFI.mjs.map +1 -0
  42. package/dist/sdk/{chunk-AKCHIYWU.mjs → chunk-YOKAA4IU.mjs} +96 -63
  43. package/dist/sdk/chunk-YOKAA4IU.mjs.map +1 -0
  44. package/dist/sdk/{config-KOKJ3PYE.mjs → config-AAB2FL22.mjs} +2 -2
  45. package/dist/sdk/{failure-condition-evaluator-LWH3NQ2S.mjs → failure-condition-evaluator-O464EJMD.mjs} +3 -3
  46. package/dist/sdk/failure-condition-evaluator-V3EJGD55.mjs +17 -0
  47. package/dist/sdk/{github-frontend-UUASYGNV.mjs → github-frontend-MSX6Q2WL.mjs} +3 -3
  48. package/dist/sdk/github-frontend-PSGUGYHT.mjs +1356 -0
  49. package/dist/sdk/github-frontend-PSGUGYHT.mjs.map +1 -0
  50. package/dist/sdk/{host-LAF3NFPZ.mjs → host-5BJ25CUZ.mjs} +2 -2
  51. package/dist/sdk/host-BYIV4QJ3.mjs +63 -0
  52. package/dist/sdk/host-BYIV4QJ3.mjs.map +1 -0
  53. package/dist/sdk/{routing-LEUV6A4K.mjs → routing-AJNUTCH7.mjs} +4 -4
  54. package/dist/sdk/routing-RIHVCEIU.mjs +25 -0
  55. package/dist/sdk/{schedule-tool-handler-EYDCUGOB.mjs → schedule-tool-handler-4O2VKNG2.mjs} +6 -6
  56. package/dist/sdk/{schedule-tool-handler-W7IB4MK3.mjs → schedule-tool-handler-BTLEDYAI.mjs} +3 -3
  57. package/dist/sdk/{schedule-tool-handler-7RGTKO24.mjs → schedule-tool-handler-R7PNPWWK.mjs} +6 -6
  58. package/dist/sdk/sdk.d.mts +3 -1
  59. package/dist/sdk/sdk.d.ts +3 -1
  60. package/dist/sdk/sdk.js +568 -168
  61. package/dist/sdk/sdk.js.map +1 -1
  62. package/dist/sdk/sdk.mjs +5 -5
  63. package/dist/sdk/{trace-helpers-NNBQNFWZ.mjs → trace-helpers-OZTZBK6T.mjs} +2 -2
  64. package/dist/sdk/trace-helpers-QQSTZGDT.mjs +25 -0
  65. package/dist/sdk/{workflow-check-provider-WW5U6R2P.mjs → workflow-check-provider-3IIKJFM4.mjs} +3 -3
  66. package/dist/sdk/workflow-check-provider-3IIKJFM4.mjs.map +1 -0
  67. package/dist/sdk/{workflow-check-provider-FLBIJQ4Z.mjs → workflow-check-provider-OM62QYHF.mjs} +6 -6
  68. package/dist/sdk/workflow-check-provider-OM62QYHF.mjs.map +1 -0
  69. package/dist/sdk/{workflow-check-provider-2G2CEXFR.mjs → workflow-check-provider-RARO4N5E.mjs} +6 -6
  70. package/dist/sdk/workflow-check-provider-RARO4N5E.mjs.map +1 -0
  71. package/dist/slack/socket-runner.d.ts.map +1 -1
  72. package/dist/traces/{run-2026-02-25T17-29-59-894Z.ndjson → run-2026-02-26T07-47-34-788Z.ndjson} +84 -84
  73. package/dist/{output/traces/run-2026-02-25T17-30-47-149Z.ndjson → traces/run-2026-02-26T07-48-25-935Z.ndjson} +1118 -1118
  74. package/dist/utils/workspace-manager.d.ts +9 -0
  75. package/dist/utils/workspace-manager.d.ts.map +1 -1
  76. package/package.json +2 -2
  77. package/dist/sdk/chunk-AKCHIYWU.mjs.map +0 -1
  78. package/dist/sdk/chunk-D3UC5KUJ.mjs.map +0 -1
  79. package/dist/sdk/chunk-N7LW3Q5B.mjs.map +0 -1
  80. package/dist/sdk/chunk-PXWWPPNF.mjs.map +0 -1
  81. /package/dist/sdk/{check-provider-registry-GKLK3I2X.mjs.map → check-provider-registry-HFPKHYTG.mjs.map} +0 -0
  82. /package/dist/sdk/{check-provider-registry-VTNNTMWC.mjs.map → check-provider-registry-HK6M4PDQ.mjs.map} +0 -0
  83. /package/dist/sdk/{check-provider-registry-WBEOZCGW.mjs.map → check-provider-registry-TG5G2TF3.mjs.map} +0 -0
  84. /package/dist/sdk/{chunk-CLQTOZKH.mjs.map → chunk-I42ZCVA5.mjs.map} +0 -0
  85. /package/dist/sdk/{chunk-PQWAAGUP.mjs.map → chunk-L3XPYQ6I.mjs.map} +0 -0
  86. /package/dist/sdk/{config-KOKJ3PYE.mjs.map → config-AAB2FL22.mjs.map} +0 -0
  87. /package/dist/sdk/{failure-condition-evaluator-LWH3NQ2S.mjs.map → failure-condition-evaluator-O464EJMD.mjs.map} +0 -0
  88. /package/dist/sdk/{routing-LEUV6A4K.mjs.map → failure-condition-evaluator-V3EJGD55.mjs.map} +0 -0
  89. /package/dist/sdk/{github-frontend-UUASYGNV.mjs.map → github-frontend-MSX6Q2WL.mjs.map} +0 -0
  90. /package/dist/sdk/{host-LAF3NFPZ.mjs.map → host-5BJ25CUZ.mjs.map} +0 -0
  91. /package/dist/sdk/{schedule-tool-handler-7RGTKO24.mjs.map → routing-AJNUTCH7.mjs.map} +0 -0
  92. /package/dist/sdk/{schedule-tool-handler-EYDCUGOB.mjs.map → routing-RIHVCEIU.mjs.map} +0 -0
  93. /package/dist/sdk/{schedule-tool-handler-W7IB4MK3.mjs.map → schedule-tool-handler-4O2VKNG2.mjs.map} +0 -0
  94. /package/dist/sdk/{trace-helpers-NNBQNFWZ.mjs.map → schedule-tool-handler-BTLEDYAI.mjs.map} +0 -0
  95. /package/dist/sdk/{workflow-check-provider-2G2CEXFR.mjs.map → schedule-tool-handler-R7PNPWWK.mjs.map} +0 -0
  96. /package/dist/sdk/{workflow-check-provider-FLBIJQ4Z.mjs.map → trace-helpers-OZTZBK6T.mjs.map} +0 -0
  97. /package/dist/sdk/{workflow-check-provider-WW5U6R2P.mjs.map → trace-helpers-QQSTZGDT.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.144';
3
- process.env.PROBE_VERSION = '0.6.0-rc259';
4
- process.env.VISOR_COMMIT_SHA = '0f8df6f53e18e9ad94507e1761debabaf533c0df';
5
- process.env.VISOR_COMMIT_SHORT = '0f8df6f';
2
+ process.env.VISOR_VERSION = '0.1.145';
3
+ process.env.PROBE_VERSION = '0.6.0-rc260';
4
+ process.env.VISOR_COMMIT_SHA = '7f399fc32c663ce91b7adbb19c6f29bcd7f41931';
5
+ process.env.VISOR_COMMIT_SHORT = '7f399fc';
6
6
  /******/ (() => { // webpackBootstrap
7
7
  /******/ var __webpack_modules__ = ({
8
8
 
@@ -164445,99 +164445,131 @@ class ConfigManager {
164445
164445
  message: `Sandbox name '${name}' contains invalid characters. Only letters, numbers, dots, hyphens, underscores allowed.`,
164446
164446
  });
164447
164447
  }
164448
- // Must have exactly one mode
164449
- const modes = [
164450
- config.image ? 'image' : null,
164451
- config.dockerfile || config.dockerfile_inline ? 'dockerfile' : null,
164452
- config.compose ? 'compose' : null,
164453
- ].filter(Boolean);
164454
- if (modes.length === 0) {
164448
+ // Validate engine field if present
164449
+ if (config.engine && !['docker', 'bubblewrap', 'seatbelt'].includes(config.engine)) {
164455
164450
  errors.push({
164456
- field: `sandboxes.${name}`,
164457
- message: `Sandbox '${name}' must specify one of: image, dockerfile, dockerfile_inline, or compose`,
164458
- });
164459
- }
164460
- else if (modes.length > 1) {
164461
- errors.push({
164462
- field: `sandboxes.${name}`,
164463
- message: `Sandbox '${name}' has multiple modes (${modes.join(', ')}). Specify exactly one.`,
164451
+ field: `sandboxes.${name}.engine`,
164452
+ message: `Sandbox '${name}' has invalid engine '${config.engine}'. Must be 'docker', 'bubblewrap', or 'seatbelt'.`,
164464
164453
  });
164465
164454
  }
164466
- // Compose mode requires service
164467
- if (config.compose && !config.service) {
164468
- errors.push({
164469
- field: `sandboxes.${name}.service`,
164470
- message: `Sandbox '${name}' uses compose mode but is missing required 'service' field`,
164471
- });
164472
- }
164473
- // Validate file paths don't contain traversal
164474
- if (config.dockerfile && /\.\./.test(config.dockerfile)) {
164475
- errors.push({
164476
- field: `sandboxes.${name}.dockerfile`,
164477
- message: `Dockerfile path '${config.dockerfile}' in sandbox '${name}' must not contain '..' path traversal`,
164478
- });
164479
- }
164480
- if (config.compose && /\.\./.test(config.compose)) {
164481
- errors.push({
164482
- field: `sandboxes.${name}.compose`,
164483
- message: `Compose file path '${config.compose}' in sandbox '${name}' must not contain '..' path traversal`,
164484
- });
164455
+ const isNativeEngine = config.engine === 'bubblewrap' || config.engine === 'seatbelt';
164456
+ if (isNativeEngine) {
164457
+ // Native engine (bubblewrap/seatbelt): reject Docker-only fields
164458
+ const dockerOnlyFields = [
164459
+ ['image', config.image],
164460
+ ['dockerfile', config.dockerfile],
164461
+ ['dockerfile_inline', config.dockerfile_inline],
164462
+ ['compose', config.compose],
164463
+ ['service', config.service],
164464
+ ['cache', config.cache],
164465
+ ['visor_path', config.visor_path],
164466
+ ['resources', config.resources],
164467
+ ];
164468
+ for (const [field, value] of dockerOnlyFields) {
164469
+ if (value !== undefined) {
164470
+ errors.push({
164471
+ field: `sandboxes.${name}.${field}`,
164472
+ message: `Sandbox '${name}' uses ${config.engine} engine but has Docker-only field '${field}'. Remove it or switch to engine: docker.`,
164473
+ });
164474
+ }
164475
+ }
164485
164476
  }
164486
- // Validate container paths are absolute and safe
164487
- if (config.workdir) {
164488
- if (!config.workdir.startsWith('/')) {
164477
+ else {
164478
+ // Docker engine (default): must have exactly one mode
164479
+ const modes = [
164480
+ config.image ? 'image' : null,
164481
+ config.dockerfile || config.dockerfile_inline ? 'dockerfile' : null,
164482
+ config.compose ? 'compose' : null,
164483
+ ].filter(Boolean);
164484
+ if (modes.length === 0) {
164489
164485
  errors.push({
164490
- field: `sandboxes.${name}.workdir`,
164491
- message: `Workdir '${config.workdir}' in sandbox '${name}' must be an absolute path (start with /)`,
164486
+ field: `sandboxes.${name}`,
164487
+ message: `Sandbox '${name}' must specify one of: image, dockerfile, dockerfile_inline, or compose`,
164492
164488
  });
164493
164489
  }
164494
- if (/\.\./.test(config.workdir)) {
164490
+ else if (modes.length > 1) {
164495
164491
  errors.push({
164496
- field: `sandboxes.${name}.workdir`,
164497
- message: `Workdir '${config.workdir}' in sandbox '${name}' must not contain '..' path traversal`,
164492
+ field: `sandboxes.${name}`,
164493
+ message: `Sandbox '${name}' has multiple modes (${modes.join(', ')}). Specify exactly one.`,
164498
164494
  });
164499
164495
  }
164500
- }
164501
- if (config.visor_path) {
164502
- if (!config.visor_path.startsWith('/')) {
164496
+ // Compose mode requires service
164497
+ if (config.compose && !config.service) {
164503
164498
  errors.push({
164504
- field: `sandboxes.${name}.visor_path`,
164505
- message: `visor_path '${config.visor_path}' in sandbox '${name}' must be an absolute path (start with /)`,
164499
+ field: `sandboxes.${name}.service`,
164500
+ message: `Sandbox '${name}' uses compose mode but is missing required 'service' field`,
164506
164501
  });
164507
164502
  }
164508
- if (/\.\./.test(config.visor_path)) {
164503
+ // Validate file paths don't contain traversal
164504
+ if (config.dockerfile && /\.\./.test(config.dockerfile)) {
164509
164505
  errors.push({
164510
- field: `sandboxes.${name}.visor_path`,
164511
- message: `visor_path '${config.visor_path}' in sandbox '${name}' must not contain '..' path traversal`,
164506
+ field: `sandboxes.${name}.dockerfile`,
164507
+ message: `Dockerfile path '${config.dockerfile}' in sandbox '${name}' must not contain '..' path traversal`,
164512
164508
  });
164513
164509
  }
164514
- }
164515
- // Validate cache paths are absolute and safe
164516
- if (config.cache?.paths) {
164517
- for (const p of config.cache.paths) {
164518
- if (!p.startsWith('/')) {
164510
+ if (config.compose && /\.\./.test(config.compose)) {
164511
+ errors.push({
164512
+ field: `sandboxes.${name}.compose`,
164513
+ message: `Compose file path '${config.compose}' in sandbox '${name}' must not contain '..' path traversal`,
164514
+ });
164515
+ }
164516
+ // Validate visor_path
164517
+ if (config.visor_path) {
164518
+ if (!config.visor_path.startsWith('/')) {
164519
164519
  errors.push({
164520
- field: `sandboxes.${name}.cache.paths`,
164521
- message: `Cache path '${p}' in sandbox '${name}' must be absolute (start with /)`,
164522
- value: p,
164520
+ field: `sandboxes.${name}.visor_path`,
164521
+ message: `visor_path '${config.visor_path}' in sandbox '${name}' must be an absolute path (start with /)`,
164523
164522
  });
164524
164523
  }
164525
- if (/\.\./.test(p)) {
164524
+ if (/\.\./.test(config.visor_path)) {
164525
+ errors.push({
164526
+ field: `sandboxes.${name}.visor_path`,
164527
+ message: `visor_path '${config.visor_path}' in sandbox '${name}' must not contain '..' path traversal`,
164528
+ });
164529
+ }
164530
+ }
164531
+ // Validate cache paths are absolute and safe
164532
+ if (config.cache?.paths) {
164533
+ for (const p of config.cache.paths) {
164534
+ if (!p.startsWith('/')) {
164535
+ errors.push({
164536
+ field: `sandboxes.${name}.cache.paths`,
164537
+ message: `Cache path '${p}' in sandbox '${name}' must be absolute (start with /)`,
164538
+ value: p,
164539
+ });
164540
+ }
164541
+ if (/\.\./.test(p)) {
164542
+ errors.push({
164543
+ field: `sandboxes.${name}.cache.paths`,
164544
+ message: `Cache path '${p}' in sandbox '${name}' must not contain '..' path traversal`,
164545
+ value: p,
164546
+ });
164547
+ }
164548
+ }
164549
+ }
164550
+ // Validate resource limits
164551
+ if (config.resources?.cpu !== undefined) {
164552
+ if (typeof config.resources.cpu !== 'number' || config.resources.cpu <= 0) {
164526
164553
  errors.push({
164527
- field: `sandboxes.${name}.cache.paths`,
164528
- message: `Cache path '${p}' in sandbox '${name}' must not contain '..' path traversal`,
164529
- value: p,
164554
+ field: `sandboxes.${name}.resources.cpu`,
164555
+ message: `CPU limit in sandbox '${name}' must be a positive number`,
164556
+ value: config.resources.cpu,
164530
164557
  });
164531
164558
  }
164532
164559
  }
164533
164560
  }
164534
- // Validate resource limits
164535
- if (config.resources?.cpu !== undefined) {
164536
- if (typeof config.resources.cpu !== 'number' || config.resources.cpu <= 0) {
164561
+ // Common validations for all engines
164562
+ if (config.workdir) {
164563
+ if (!config.workdir.startsWith('/')) {
164537
164564
  errors.push({
164538
- field: `sandboxes.${name}.resources.cpu`,
164539
- message: `CPU limit in sandbox '${name}' must be a positive number`,
164540
- value: config.resources.cpu,
164565
+ field: `sandboxes.${name}.workdir`,
164566
+ message: `Workdir '${config.workdir}' in sandbox '${name}' must be an absolute path (start with /)`,
164567
+ });
164568
+ }
164569
+ if (/\.\./.test(config.workdir)) {
164570
+ errors.push({
164571
+ field: `sandboxes.${name}.workdir`,
164572
+ message: `Workdir '${config.workdir}' in sandbox '${name}' must not contain '..' path traversal`,
164541
164573
  });
164542
164574
  }
164543
164575
  }
@@ -171448,6 +171480,11 @@ exports.configSchema = {
171448
171480
  SandboxConfig: {
171449
171481
  type: 'object',
171450
171482
  properties: {
171483
+ engine: {
171484
+ type: 'string',
171485
+ enum: ['docker', 'bubblewrap', 'seatbelt'],
171486
+ description: "Sandbox engine type: 'docker' (default), 'bubblewrap' (Linux namespaces), or 'seatbelt' (macOS sandbox-exec)",
171487
+ },
171451
171488
  image: {
171452
171489
  type: 'string',
171453
171490
  description: 'Docker image to use (e.g., "node:20-alpine")',
@@ -186591,6 +186628,7 @@ class McpCheckProvider extends check_provider_interface_1.CheckProvider {
186591
186628
  outputs: this.buildOutputContext(dependencyResults),
186592
186629
  args: sessionInfo?.args || {},
186593
186630
  env: this.getSafeEnvironmentVariables(),
186631
+ inputs: config.workflowInputs || sessionInfo?.workflowInputs || {},
186594
186632
  };
186595
186633
  // Render method arguments if needed
186596
186634
  let methodArgs = cfg.methodArgs || {};
@@ -190152,6 +190190,150 @@ class PRReviewer {
190152
190190
  exports.PRReviewer = PRReviewer;
190153
190191
 
190154
190192
 
190193
+ /***/ }),
190194
+
190195
+ /***/ 11207:
190196
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
190197
+
190198
+ "use strict";
190199
+
190200
+ /**
190201
+ * Bubblewrap-based sandbox implementation.
190202
+ * Uses Linux kernel namespaces for lightweight process isolation (~5-50ms overhead).
190203
+ * Requires the `bwrap` binary to be installed on the host.
190204
+ */
190205
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
190206
+ exports.BubblewrapSandbox = void 0;
190207
+ const util_1 = __nccwpck_require__(39023);
190208
+ const child_process_1 = __nccwpck_require__(35317);
190209
+ const fs_1 = __nccwpck_require__(79896);
190210
+ const path_1 = __nccwpck_require__(16928);
190211
+ const logger_1 = __nccwpck_require__(86999);
190212
+ const sandbox_telemetry_1 = __nccwpck_require__(34826);
190213
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
190214
+ const EXEC_MAX_BUFFER = 50 * 1024 * 1024; // 50MB
190215
+ class BubblewrapSandbox {
190216
+ name;
190217
+ config;
190218
+ repoPath;
190219
+ constructor(name, config, repoPath) {
190220
+ this.name = name;
190221
+ this.config = config;
190222
+ this.repoPath = (0, path_1.resolve)(repoPath);
190223
+ }
190224
+ /**
190225
+ * Check if bwrap binary is available on the system.
190226
+ */
190227
+ static async isAvailable() {
190228
+ try {
190229
+ await execFileAsync('which', ['bwrap'], { timeout: 5000 });
190230
+ return true;
190231
+ }
190232
+ catch {
190233
+ return false;
190234
+ }
190235
+ }
190236
+ /**
190237
+ * Execute a command inside a bubblewrap sandbox.
190238
+ * Each exec creates a fresh namespace — no persistent container.
190239
+ */
190240
+ async exec(options) {
190241
+ const args = this.buildArgs(options);
190242
+ args.push('--', '/bin/sh', '-c', options.command);
190243
+ logger_1.logger.debug(`[BubblewrapSandbox] Executing in sandbox '${this.name}': ${options.command.slice(0, 100)}`);
190244
+ try {
190245
+ const { stdout, stderr } = await execFileAsync('bwrap', args, {
190246
+ maxBuffer: options.maxBuffer || EXEC_MAX_BUFFER,
190247
+ timeout: options.timeoutMs || 600000,
190248
+ });
190249
+ (0, sandbox_telemetry_1.addEvent)('visor.sandbox.bwrap.exec', {
190250
+ 'visor.sandbox.name': this.name,
190251
+ 'visor.sandbox.exit_code': 0,
190252
+ });
190253
+ return { stdout, stderr, exitCode: 0 };
190254
+ }
190255
+ catch (err) {
190256
+ const execErr = err;
190257
+ const exitCode = typeof execErr.code === 'number' ? execErr.code : 1;
190258
+ (0, sandbox_telemetry_1.addEvent)('visor.sandbox.bwrap.exec', {
190259
+ 'visor.sandbox.name': this.name,
190260
+ 'visor.sandbox.exit_code': exitCode,
190261
+ });
190262
+ return {
190263
+ stdout: execErr.stdout || '',
190264
+ stderr: execErr.stderr || '',
190265
+ exitCode,
190266
+ };
190267
+ }
190268
+ }
190269
+ /**
190270
+ * No-op: bubblewrap processes are ephemeral (no persistent container to stop).
190271
+ */
190272
+ async stop() {
190273
+ // Nothing to clean up — bwrap processes exit when the command finishes,
190274
+ // and --die-with-parent ensures cleanup if the parent dies.
190275
+ }
190276
+ /**
190277
+ * Build the bwrap command-line arguments.
190278
+ */
190279
+ buildArgs(options) {
190280
+ const workdir = this.config.workdir || '/workspace';
190281
+ const args = [];
190282
+ // Read-only system directories
190283
+ args.push('--ro-bind', '/usr', '/usr');
190284
+ args.push('--ro-bind', '/bin', '/bin');
190285
+ // /lib and /lib64 may not exist on all distros (e.g., Alpine uses /usr/lib)
190286
+ if ((0, fs_1.existsSync)('/lib')) {
190287
+ args.push('--ro-bind', '/lib', '/lib');
190288
+ }
190289
+ if ((0, fs_1.existsSync)('/lib64')) {
190290
+ args.push('--ro-bind', '/lib64', '/lib64');
190291
+ }
190292
+ // DNS resolution and TLS certificates
190293
+ if ((0, fs_1.existsSync)('/etc/resolv.conf')) {
190294
+ args.push('--ro-bind', '/etc/resolv.conf', '/etc/resolv.conf');
190295
+ }
190296
+ if ((0, fs_1.existsSync)('/etc/ssl')) {
190297
+ args.push('--ro-bind', '/etc/ssl', '/etc/ssl');
190298
+ }
190299
+ // Virtual filesystems
190300
+ args.push('--dev', '/dev');
190301
+ args.push('--proc', '/proc');
190302
+ args.push('--tmpfs', '/tmp');
190303
+ args.push('--tmpfs', '/root');
190304
+ // Workspace mount — the only writable directory (unless read_only)
190305
+ if (this.config.read_only) {
190306
+ args.push('--ro-bind', this.repoPath, workdir);
190307
+ }
190308
+ else {
190309
+ args.push('--bind', this.repoPath, workdir);
190310
+ }
190311
+ // Working directory inside sandbox
190312
+ args.push('--chdir', workdir);
190313
+ // Namespace isolation
190314
+ args.push('--unshare-pid');
190315
+ args.push('--new-session');
190316
+ args.push('--die-with-parent');
190317
+ // Network isolation
190318
+ if (this.config.network === false) {
190319
+ args.push('--unshare-net');
190320
+ }
190321
+ // Clean environment — only explicitly passed vars are visible
190322
+ args.push('--clearenv');
190323
+ // Pass filtered environment variables.
190324
+ // Safe: execFile passes each arg as a separate argv entry — no shell interpretation.
190325
+ for (const [key, value] of Object.entries(options.env)) {
190326
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
190327
+ throw new Error(`Invalid environment variable name: '${key}'`);
190328
+ }
190329
+ args.push('--setenv', key, value);
190330
+ }
190331
+ return args;
190332
+ }
190333
+ }
190334
+ exports.BubblewrapSandbox = BubblewrapSandbox;
190335
+
190336
+
190155
190337
  /***/ }),
190156
190338
 
190157
190339
  /***/ 10878:
@@ -190978,8 +191160,9 @@ function filterEnvForSandbox(checkEnv, hostEnv, passthroughPatterns, defaultPatt
190978
191160
  "use strict";
190979
191161
 
190980
191162
  /**
190981
- * SandboxManager — lifecycle management for Docker sandbox environments.
190982
- * Handles lazy container startup, reuse, exec routing, and cleanup.
191163
+ * SandboxManager — lifecycle management for sandbox environments.
191164
+ * Handles lazy container/process startup, reuse, exec routing, and cleanup.
191165
+ * Supports Docker (image, compose), Bubblewrap (Linux namespaces), and Seatbelt (macOS sandbox-exec) engines.
190983
191166
  */
190984
191167
  Object.defineProperty(exports, "__esModule", ({ value: true }));
190985
191168
  exports.SandboxManager = void 0;
@@ -191043,6 +191226,20 @@ class SandboxManager {
191043
191226
  throw new Error(`Sandbox '${name}' is not defined`);
191044
191227
  }
191045
191228
  const mode = config.compose ? 'compose' : 'image';
191229
+ // Bubblewrap engine: ephemeral per-exec, no persistent container
191230
+ if (config.engine === 'bubblewrap') {
191231
+ const { BubblewrapSandbox } = __nccwpck_require__(11207);
191232
+ const instance = new BubblewrapSandbox(name, config, this.repoPath);
191233
+ this.instances.set(name, instance);
191234
+ return instance;
191235
+ }
191236
+ // Seatbelt engine: macOS sandbox-exec, ephemeral per-exec
191237
+ if (config.engine === 'seatbelt') {
191238
+ const { SeatbeltSandbox } = __nccwpck_require__(46429);
191239
+ const instance = new SeatbeltSandbox(name, config, this.repoPath);
191240
+ this.instances.set(name, instance);
191241
+ return instance;
191242
+ }
191046
191243
  return (0, sandbox_telemetry_1.withActiveSpan)('visor.sandbox.start', {
191047
191244
  'visor.sandbox.name': name,
191048
191245
  'visor.sandbox.mode': mode,
@@ -191171,6 +191368,165 @@ function setSpanError(err) {
191171
191368
  }
191172
191369
 
191173
191370
 
191371
+ /***/ }),
191372
+
191373
+ /***/ 46429:
191374
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
191375
+
191376
+ "use strict";
191377
+
191378
+ /**
191379
+ * macOS Seatbelt sandbox implementation.
191380
+ * Uses Apple's sandbox-exec with dynamically-generated SBPL profiles
191381
+ * for lightweight process isolation on macOS.
191382
+ * Requires the `sandbox-exec` binary (ships with macOS).
191383
+ */
191384
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
191385
+ exports.SeatbeltSandbox = void 0;
191386
+ const util_1 = __nccwpck_require__(39023);
191387
+ const child_process_1 = __nccwpck_require__(35317);
191388
+ const path_1 = __nccwpck_require__(16928);
191389
+ const fs_1 = __nccwpck_require__(79896);
191390
+ const logger_1 = __nccwpck_require__(86999);
191391
+ const sandbox_telemetry_1 = __nccwpck_require__(34826);
191392
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
191393
+ const EXEC_MAX_BUFFER = 50 * 1024 * 1024; // 50MB
191394
+ class SeatbeltSandbox {
191395
+ name;
191396
+ config;
191397
+ repoPath;
191398
+ constructor(name, config, repoPath) {
191399
+ this.name = name;
191400
+ this.config = config;
191401
+ // Resolve symlinks — macOS has /var → /private/var, /tmp → /private/tmp etc.
191402
+ // sandbox-exec operates on real paths, so we must resolve before building profiles.
191403
+ this.repoPath = (0, fs_1.realpathSync)((0, path_1.resolve)(repoPath));
191404
+ }
191405
+ /**
191406
+ * Check if sandbox-exec binary is available on the system.
191407
+ */
191408
+ static async isAvailable() {
191409
+ try {
191410
+ await execFileAsync('which', ['sandbox-exec'], { timeout: 5000 });
191411
+ return true;
191412
+ }
191413
+ catch {
191414
+ return false;
191415
+ }
191416
+ }
191417
+ /**
191418
+ * Execute a command inside a macOS seatbelt sandbox.
191419
+ * Each exec creates a fresh sandbox process — no persistent container.
191420
+ */
191421
+ async exec(options) {
191422
+ const profile = this.buildProfile();
191423
+ // Validate env var names
191424
+ for (const key of Object.keys(options.env)) {
191425
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
191426
+ throw new Error(`Invalid environment variable name: '${key}'`);
191427
+ }
191428
+ }
191429
+ // Build args: sandbox-exec -p '<profile>' /usr/bin/env -i KEY=VAL ... /bin/sh -c '<command>'
191430
+ const args = ['-p', profile];
191431
+ // Use env -i to clear inherited environment, then set explicit vars
191432
+ args.push('/usr/bin/env', '-i');
191433
+ for (const [key, value] of Object.entries(options.env)) {
191434
+ args.push(`${key}=${value}`);
191435
+ }
191436
+ args.push('/bin/sh', '-c', options.command);
191437
+ logger_1.logger.debug(`[SeatbeltSandbox] Executing in sandbox '${this.name}': ${options.command.slice(0, 100)}`);
191438
+ try {
191439
+ const { stdout, stderr } = await execFileAsync('sandbox-exec', args, {
191440
+ maxBuffer: options.maxBuffer || EXEC_MAX_BUFFER,
191441
+ timeout: options.timeoutMs || 600000,
191442
+ cwd: this.repoPath,
191443
+ });
191444
+ (0, sandbox_telemetry_1.addEvent)('visor.sandbox.seatbelt.exec', {
191445
+ 'visor.sandbox.name': this.name,
191446
+ 'visor.sandbox.exit_code': 0,
191447
+ });
191448
+ return { stdout, stderr, exitCode: 0 };
191449
+ }
191450
+ catch (err) {
191451
+ const execErr = err;
191452
+ const exitCode = typeof execErr.code === 'number' ? execErr.code : 1;
191453
+ (0, sandbox_telemetry_1.addEvent)('visor.sandbox.seatbelt.exec', {
191454
+ 'visor.sandbox.name': this.name,
191455
+ 'visor.sandbox.exit_code': exitCode,
191456
+ });
191457
+ return {
191458
+ stdout: execErr.stdout || '',
191459
+ stderr: execErr.stderr || '',
191460
+ exitCode,
191461
+ };
191462
+ }
191463
+ }
191464
+ /**
191465
+ * No-op: sandbox-exec processes are ephemeral (no persistent container to stop).
191466
+ */
191467
+ async stop() {
191468
+ // Nothing to clean up — sandbox-exec processes exit when the command finishes.
191469
+ }
191470
+ /**
191471
+ * Escape a path for use inside an SBPL profile string.
191472
+ * Escapes backslashes and double quotes.
191473
+ */
191474
+ escapePath(p) {
191475
+ return p.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
191476
+ }
191477
+ /**
191478
+ * Build the SBPL (Seatbelt Profile Language) profile string.
191479
+ */
191480
+ buildProfile() {
191481
+ const repoPath = this.escapePath(this.repoPath);
191482
+ const lines = [];
191483
+ lines.push('(version 1)');
191484
+ lines.push('(deny default)');
191485
+ // Allow basic process execution
191486
+ lines.push('(allow process-exec)');
191487
+ lines.push('(allow process-fork)');
191488
+ // Allow read access to system paths.
191489
+ // macOS uses symlinks: /var → /private/var, /tmp → /private/tmp, /etc → /private/etc.
191490
+ // We include both the symlink paths and /private to cover resolution.
191491
+ lines.push('(allow file-read*');
191492
+ lines.push(' (literal "/")');
191493
+ lines.push(' (subpath "/usr")');
191494
+ lines.push(' (subpath "/bin")');
191495
+ lines.push(' (subpath "/sbin")');
191496
+ lines.push(' (subpath "/Library")');
191497
+ lines.push(' (subpath "/System")');
191498
+ lines.push(' (subpath "/private")');
191499
+ lines.push(' (subpath "/var")');
191500
+ lines.push(' (subpath "/etc")');
191501
+ lines.push(' (subpath "/dev")');
191502
+ lines.push(' (subpath "/tmp"))');
191503
+ // Allow write to /tmp and /dev
191504
+ lines.push('(allow file-write*');
191505
+ lines.push(' (subpath "/tmp")');
191506
+ lines.push(' (subpath "/private/tmp")');
191507
+ lines.push(' (subpath "/dev"))');
191508
+ // Allow xcrun cache writes (macOS git/Xcode tools write to /var/folders/.../T/xcrun_db-*)
191509
+ lines.push('(allow file-write* (regex #"/private/var/folders/.*/T/xcrun_db"))');
191510
+ // Workspace read access
191511
+ lines.push(`(allow file-read* (subpath "${repoPath}"))`);
191512
+ // Workspace write access (unless read_only)
191513
+ if (!this.config.read_only) {
191514
+ lines.push(`(allow file-write* (subpath "${repoPath}"))`);
191515
+ }
191516
+ // Network access (unless explicitly disabled)
191517
+ if (this.config.network !== false) {
191518
+ lines.push('(allow network*)');
191519
+ }
191520
+ // Allow sysctl, mach lookups, signal for basic process operation
191521
+ lines.push('(allow sysctl-read)');
191522
+ lines.push('(allow mach-lookup)');
191523
+ lines.push('(allow signal)');
191524
+ return lines.join('\n');
191525
+ }
191526
+ }
191527
+ exports.SeatbeltSandbox = SeatbeltSandbox;
191528
+
191529
+
191174
191530
  /***/ }),
191175
191531
 
191176
191532
  /***/ 50504:
@@ -196743,7 +197099,9 @@ const cache_prewarmer_1 = __nccwpck_require__(50200);
196743
197099
  const rate_limiter_1 = __nccwpck_require__(53065);
196744
197100
  const trace_helpers_1 = __nccwpck_require__(75338);
196745
197101
  const scheduler_1 = __nccwpck_require__(28404);
197102
+ const crypto_1 = __nccwpck_require__(76982);
196746
197103
  const slack_output_adapter_1 = __nccwpck_require__(45330);
197104
+ const workspace_manager_1 = __nccwpck_require__(6134);
196747
197105
  class SlackSocketRunner {
196748
197106
  appToken;
196749
197107
  endpoint;
@@ -196874,6 +197232,8 @@ class SlackSocketRunner {
196874
197232
  }
196875
197233
  const url = await this.openConnection();
196876
197234
  await this.connect(url);
197235
+ // Clean up stale workspace directories from previous runs
197236
+ workspace_manager_1.WorkspaceManager.cleanupStale().catch(() => { });
196877
197237
  }
196878
197238
  async openConnection() {
196879
197239
  const resp = await fetch('https://slack.com/api/apps.connections.open', {
@@ -197169,6 +197529,22 @@ class SlackSocketRunner {
197169
197529
  return this.cfg;
197170
197530
  }
197171
197531
  })();
197532
+ // Derive stable workspace name from Slack thread identity so all messages
197533
+ // in the same thread share the same workspace directory (git checkouts persist).
197534
+ const wsChannel = String(ev.channel || '');
197535
+ const wsThreadTs = String(ev.thread_ts || ev.ts || ev.event_ts || '');
197536
+ if (wsChannel && wsThreadTs) {
197537
+ const hash = (0, crypto_1.createHash)('sha256')
197538
+ .update(`${wsChannel}:${wsThreadTs}`)
197539
+ .digest('hex')
197540
+ .slice(0, 8);
197541
+ const workspaceName = `slack-${hash}`;
197542
+ if (!cfgForRun.workspace) {
197543
+ cfgForRun.workspace = {};
197544
+ }
197545
+ cfgForRun.workspace.name = workspaceName;
197546
+ cfgForRun.workspace.cleanup_on_exit = false;
197547
+ }
197172
197548
  // Seed first message for this thread to allow initial human-input to consume it exactly once
197173
197549
  try {
197174
197550
  const { getPromptStateManager } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(27716)));
@@ -220309,17 +220685,36 @@ class WorkspaceManager {
220309
220685
  // Check if original path is a git repository
220310
220686
  const isGitRepo = await this.isGitRepository(this.originalPath);
220311
220687
  if (isGitRepo) {
220312
- // Create worktree for main project
220313
- await this.createMainProjectWorktree(mainProjectPath);
220688
+ // Check if main project worktree already exists (reused workspace, e.g. Slack thread)
220689
+ const exists = await this.pathExists(mainProjectPath);
220690
+ if (exists) {
220691
+ logger_1.logger.info(`[Workspace] Reusing existing main project worktree: ${mainProjectPath}`);
220692
+ const isValid = await this.isGitRepository(mainProjectPath);
220693
+ if (!isValid) {
220694
+ logger_1.logger.warn(`[Workspace] Existing path is not a valid git dir, recreating`);
220695
+ await fsp.rm(mainProjectPath, { recursive: true, force: true });
220696
+ try {
220697
+ await command_executor_1.commandExecutor.execute(`git -C ${shellEscape(this.originalPath)} worktree prune`, { timeout: 10000 });
220698
+ }
220699
+ catch { }
220700
+ await this.createMainProjectWorktree(mainProjectPath);
220701
+ }
220702
+ }
220703
+ else {
220704
+ await this.createMainProjectWorktree(mainProjectPath);
220705
+ }
220314
220706
  }
220315
220707
  else {
220316
220708
  // If not a git repo, create a symlink instead
220317
220709
  logger_1.logger.debug(`Original path is not a git repo, creating symlink`);
220318
- try {
220319
- await fsp.symlink(this.originalPath, mainProjectPath);
220320
- }
220321
- catch (error) {
220322
- throw new Error(`Failed to create symlink for main project: ${error}`);
220710
+ const exists = await this.pathExists(mainProjectPath);
220711
+ if (!exists) {
220712
+ try {
220713
+ await fsp.symlink(this.originalPath, mainProjectPath);
220714
+ }
220715
+ catch (error) {
220716
+ throw new Error(`Failed to create symlink for main project: ${error}`);
220717
+ }
220323
220718
  }
220324
220719
  }
220325
220720
  // Register cleanup handlers
@@ -220389,6 +220784,16 @@ class WorkspaceManager {
220389
220784
  * @param timeout Maximum time to wait for active operations (default: 60s)
220390
220785
  */
220391
220786
  async cleanup(timeout = 60000) {
220787
+ // Respect cleanupOnExit flag — persisted workspaces (e.g. Slack threads) should not be cleaned up
220788
+ if (!this.config.cleanupOnExit) {
220789
+ logger_1.logger.debug(`[Workspace] Skipping cleanup (cleanupOnExit=false): ${this.workspacePath}`);
220790
+ WorkspaceManager.instances.delete(this.sessionId);
220791
+ this.initialized = false;
220792
+ this.mainProjectInfo = null;
220793
+ this.projects.clear();
220794
+ this.usedNames.clear();
220795
+ return;
220796
+ }
220392
220797
  logger_1.logger.info(`Cleaning up workspace: ${this.workspacePath} (active operations: ${this.activeOperations})`);
220393
220798
  // If there are active operations, wait for them to complete
220394
220799
  if (this.activeOperations > 0) {
@@ -220444,6 +220849,70 @@ class WorkspaceManager {
220444
220849
  logger_1.logger.warn(`Failed to cleanup workspace: ${error}`);
220445
220850
  }
220446
220851
  }
220852
+ /**
220853
+ * Check if a path exists (file or directory).
220854
+ */
220855
+ async pathExists(p) {
220856
+ try {
220857
+ await fsp.access(p);
220858
+ return true;
220859
+ }
220860
+ catch {
220861
+ return false;
220862
+ }
220863
+ }
220864
+ /**
220865
+ * Clean up stale workspace directories older than maxAge.
220866
+ * Call periodically (e.g. at socket-runner startup) to prevent disk bloat.
220867
+ */
220868
+ static async cleanupStale(basePath = process.env.VISOR_WORKSPACE_PATH || '/tmp/visor-workspaces', maxAgeMs = 24 * 60 * 60 * 1000) {
220869
+ let cleaned = 0;
220870
+ try {
220871
+ const entries = await fsp.readdir(basePath, { withFileTypes: true });
220872
+ const now = Date.now();
220873
+ for (const entry of entries) {
220874
+ if (!entry.isDirectory())
220875
+ continue;
220876
+ const dirPath = path.join(basePath, entry.name);
220877
+ try {
220878
+ const stat = await fsp.stat(dirPath);
220879
+ if (now - stat.mtimeMs > maxAgeMs) {
220880
+ // Prune any git worktrees before removing the directory
220881
+ try {
220882
+ const subdirs = await fsp.readdir(dirPath, { withFileTypes: true });
220883
+ for (const sub of subdirs) {
220884
+ if (!sub.isDirectory())
220885
+ continue;
220886
+ const subPath = path.join(dirPath, sub.name);
220887
+ const gitFilePath = path.join(subPath, '.git');
220888
+ try {
220889
+ const gitContent = await fsp.readFile(gitFilePath, 'utf-8');
220890
+ const match = gitContent.match(/gitdir:\s*(.+)/);
220891
+ if (match) {
220892
+ const worktreeGitDir = match[1].trim();
220893
+ const repoGitDir = worktreeGitDir.replace(/\/\.git\/worktrees\/.*$/, '');
220894
+ await command_executor_1.commandExecutor.execute(`git -C ${shellEscape(repoGitDir)} worktree remove ${shellEscape(subPath)} --force`, { timeout: 10000 });
220895
+ }
220896
+ }
220897
+ catch { }
220898
+ }
220899
+ }
220900
+ catch { }
220901
+ await fsp.rm(dirPath, { recursive: true, force: true });
220902
+ cleaned++;
220903
+ }
220904
+ }
220905
+ catch { }
220906
+ }
220907
+ if (cleaned > 0) {
220908
+ logger_1.logger.info(`[Workspace] Cleaned up ${cleaned} stale workspace(s) from ${basePath}`);
220909
+ }
220910
+ }
220911
+ catch (error) {
220912
+ logger_1.logger.debug(`[Workspace] Stale cleanup error: ${error}`);
220913
+ }
220914
+ return cleaned;
220915
+ }
220447
220916
  /**
220448
220917
  * Create worktree for the main project
220449
220918
  *
@@ -263892,7 +264361,7 @@ var require_package2 = __commonJS({
263892
264361
  module2.exports = {
263893
264362
  name: "@aws-sdk/client-bedrock-runtime",
263894
264363
  description: "AWS SDK for JavaScript Bedrock Runtime Client for Node.js, Browser and React Native",
263895
- version: "3.997.0",
264364
+ version: "3.998.0",
263896
264365
  scripts: {
263897
264366
  build: "concurrently 'yarn:build:types' 'yarn:build:es' && yarn build:cjs",
263898
264367
  "build:cjs": "node ../../scripts/compilation/inline client-bedrock-runtime",
@@ -263912,49 +264381,49 @@ var require_package2 = __commonJS({
263912
264381
  dependencies: {
263913
264382
  "@aws-crypto/sha256-browser": "5.2.0",
263914
264383
  "@aws-crypto/sha256-js": "5.2.0",
263915
- "@aws-sdk/core": "^3.973.13",
263916
- "@aws-sdk/credential-provider-node": "^3.972.12",
263917
- "@aws-sdk/eventstream-handler-node": "^3.972.7",
263918
- "@aws-sdk/middleware-eventstream": "^3.972.4",
263919
- "@aws-sdk/middleware-host-header": "^3.972.4",
263920
- "@aws-sdk/middleware-logger": "^3.972.4",
263921
- "@aws-sdk/middleware-recursion-detection": "^3.972.4",
263922
- "@aws-sdk/middleware-user-agent": "^3.972.13",
263923
- "@aws-sdk/middleware-websocket": "^3.972.8",
263924
- "@aws-sdk/region-config-resolver": "^3.972.4",
263925
- "@aws-sdk/token-providers": "3.997.0",
263926
- "@aws-sdk/types": "^3.973.2",
263927
- "@aws-sdk/util-endpoints": "^3.996.1",
263928
- "@aws-sdk/util-user-agent-browser": "^3.972.4",
263929
- "@aws-sdk/util-user-agent-node": "^3.972.12",
263930
- "@smithy/config-resolver": "^4.4.7",
263931
- "@smithy/core": "^3.23.4",
263932
- "@smithy/eventstream-serde-browser": "^4.2.9",
263933
- "@smithy/eventstream-serde-config-resolver": "^4.3.9",
263934
- "@smithy/eventstream-serde-node": "^4.2.9",
263935
- "@smithy/fetch-http-handler": "^5.3.10",
263936
- "@smithy/hash-node": "^4.2.9",
263937
- "@smithy/invalid-dependency": "^4.2.9",
263938
- "@smithy/middleware-content-length": "^4.2.9",
263939
- "@smithy/middleware-endpoint": "^4.4.18",
263940
- "@smithy/middleware-retry": "^4.4.35",
263941
- "@smithy/middleware-serde": "^4.2.10",
263942
- "@smithy/middleware-stack": "^4.2.9",
263943
- "@smithy/node-config-provider": "^4.3.9",
263944
- "@smithy/node-http-handler": "^4.4.11",
263945
- "@smithy/protocol-http": "^5.3.9",
263946
- "@smithy/smithy-client": "^4.11.7",
263947
- "@smithy/types": "^4.12.1",
263948
- "@smithy/url-parser": "^4.2.9",
264384
+ "@aws-sdk/core": "^3.973.14",
264385
+ "@aws-sdk/credential-provider-node": "^3.972.13",
264386
+ "@aws-sdk/eventstream-handler-node": "^3.972.8",
264387
+ "@aws-sdk/middleware-eventstream": "^3.972.5",
264388
+ "@aws-sdk/middleware-host-header": "^3.972.5",
264389
+ "@aws-sdk/middleware-logger": "^3.972.5",
264390
+ "@aws-sdk/middleware-recursion-detection": "^3.972.5",
264391
+ "@aws-sdk/middleware-user-agent": "^3.972.14",
264392
+ "@aws-sdk/middleware-websocket": "^3.972.9",
264393
+ "@aws-sdk/region-config-resolver": "^3.972.5",
264394
+ "@aws-sdk/token-providers": "3.998.0",
264395
+ "@aws-sdk/types": "^3.973.3",
264396
+ "@aws-sdk/util-endpoints": "^3.996.2",
264397
+ "@aws-sdk/util-user-agent-browser": "^3.972.5",
264398
+ "@aws-sdk/util-user-agent-node": "^3.972.13",
264399
+ "@smithy/config-resolver": "^4.4.9",
264400
+ "@smithy/core": "^3.23.6",
264401
+ "@smithy/eventstream-serde-browser": "^4.2.10",
264402
+ "@smithy/eventstream-serde-config-resolver": "^4.3.10",
264403
+ "@smithy/eventstream-serde-node": "^4.2.10",
264404
+ "@smithy/fetch-http-handler": "^5.3.11",
264405
+ "@smithy/hash-node": "^4.2.10",
264406
+ "@smithy/invalid-dependency": "^4.2.10",
264407
+ "@smithy/middleware-content-length": "^4.2.10",
264408
+ "@smithy/middleware-endpoint": "^4.4.20",
264409
+ "@smithy/middleware-retry": "^4.4.37",
264410
+ "@smithy/middleware-serde": "^4.2.11",
264411
+ "@smithy/middleware-stack": "^4.2.10",
264412
+ "@smithy/node-config-provider": "^4.3.10",
264413
+ "@smithy/node-http-handler": "^4.4.12",
264414
+ "@smithy/protocol-http": "^5.3.10",
264415
+ "@smithy/smithy-client": "^4.12.0",
264416
+ "@smithy/types": "^4.13.0",
264417
+ "@smithy/url-parser": "^4.2.10",
263949
264418
  "@smithy/util-base64": "^4.3.1",
263950
264419
  "@smithy/util-body-length-browser": "^4.2.1",
263951
264420
  "@smithy/util-body-length-node": "^4.2.2",
263952
- "@smithy/util-defaults-mode-browser": "^4.3.34",
263953
- "@smithy/util-defaults-mode-node": "^4.2.37",
263954
- "@smithy/util-endpoints": "^3.2.9",
263955
- "@smithy/util-middleware": "^4.2.9",
263956
- "@smithy/util-retry": "^4.2.9",
263957
- "@smithy/util-stream": "^4.5.14",
264421
+ "@smithy/util-defaults-mode-browser": "^4.3.36",
264422
+ "@smithy/util-defaults-mode-node": "^4.2.39",
264423
+ "@smithy/util-endpoints": "^3.3.1",
264424
+ "@smithy/util-middleware": "^4.2.10",
264425
+ "@smithy/util-retry": "^4.2.10",
264426
+ "@smithy/util-stream": "^4.5.15",
263958
264427
  "@smithy/util-utf8": "^4.2.1",
263959
264428
  tslib: "^2.6.2"
263960
264429
  },
@@ -264673,7 +265142,7 @@ var init_package = __esm({
264673
265142
  "node_modules/@aws-sdk/nested-clients/package.json"() {
264674
265143
  package_default = {
264675
265144
  name: "@aws-sdk/nested-clients",
264676
- version: "3.996.1",
265145
+ version: "3.996.2",
264677
265146
  description: "Nested clients for AWS SDK packages.",
264678
265147
  main: "./dist-cjs/index.js",
264679
265148
  module: "./dist-es/index.js",
@@ -264702,40 +265171,40 @@ var init_package = __esm({
264702
265171
  dependencies: {
264703
265172
  "@aws-crypto/sha256-browser": "5.2.0",
264704
265173
  "@aws-crypto/sha256-js": "5.2.0",
264705
- "@aws-sdk/core": "^3.973.13",
264706
- "@aws-sdk/middleware-host-header": "^3.972.4",
264707
- "@aws-sdk/middleware-logger": "^3.972.4",
264708
- "@aws-sdk/middleware-recursion-detection": "^3.972.4",
264709
- "@aws-sdk/middleware-user-agent": "^3.972.13",
264710
- "@aws-sdk/region-config-resolver": "^3.972.4",
264711
- "@aws-sdk/types": "^3.973.2",
264712
- "@aws-sdk/util-endpoints": "^3.996.1",
264713
- "@aws-sdk/util-user-agent-browser": "^3.972.4",
264714
- "@aws-sdk/util-user-agent-node": "^3.972.12",
264715
- "@smithy/config-resolver": "^4.4.7",
264716
- "@smithy/core": "^3.23.4",
264717
- "@smithy/fetch-http-handler": "^5.3.10",
264718
- "@smithy/hash-node": "^4.2.9",
264719
- "@smithy/invalid-dependency": "^4.2.9",
264720
- "@smithy/middleware-content-length": "^4.2.9",
264721
- "@smithy/middleware-endpoint": "^4.4.18",
264722
- "@smithy/middleware-retry": "^4.4.35",
264723
- "@smithy/middleware-serde": "^4.2.10",
264724
- "@smithy/middleware-stack": "^4.2.9",
264725
- "@smithy/node-config-provider": "^4.3.9",
264726
- "@smithy/node-http-handler": "^4.4.11",
264727
- "@smithy/protocol-http": "^5.3.9",
264728
- "@smithy/smithy-client": "^4.11.7",
264729
- "@smithy/types": "^4.12.1",
264730
- "@smithy/url-parser": "^4.2.9",
265174
+ "@aws-sdk/core": "^3.973.14",
265175
+ "@aws-sdk/middleware-host-header": "^3.972.5",
265176
+ "@aws-sdk/middleware-logger": "^3.972.5",
265177
+ "@aws-sdk/middleware-recursion-detection": "^3.972.5",
265178
+ "@aws-sdk/middleware-user-agent": "^3.972.14",
265179
+ "@aws-sdk/region-config-resolver": "^3.972.5",
265180
+ "@aws-sdk/types": "^3.973.3",
265181
+ "@aws-sdk/util-endpoints": "^3.996.2",
265182
+ "@aws-sdk/util-user-agent-browser": "^3.972.5",
265183
+ "@aws-sdk/util-user-agent-node": "^3.972.13",
265184
+ "@smithy/config-resolver": "^4.4.9",
265185
+ "@smithy/core": "^3.23.6",
265186
+ "@smithy/fetch-http-handler": "^5.3.11",
265187
+ "@smithy/hash-node": "^4.2.10",
265188
+ "@smithy/invalid-dependency": "^4.2.10",
265189
+ "@smithy/middleware-content-length": "^4.2.10",
265190
+ "@smithy/middleware-endpoint": "^4.4.20",
265191
+ "@smithy/middleware-retry": "^4.4.37",
265192
+ "@smithy/middleware-serde": "^4.2.11",
265193
+ "@smithy/middleware-stack": "^4.2.10",
265194
+ "@smithy/node-config-provider": "^4.3.10",
265195
+ "@smithy/node-http-handler": "^4.4.12",
265196
+ "@smithy/protocol-http": "^5.3.10",
265197
+ "@smithy/smithy-client": "^4.12.0",
265198
+ "@smithy/types": "^4.13.0",
265199
+ "@smithy/url-parser": "^4.2.10",
264731
265200
  "@smithy/util-base64": "^4.3.1",
264732
265201
  "@smithy/util-body-length-browser": "^4.2.1",
264733
265202
  "@smithy/util-body-length-node": "^4.2.2",
264734
- "@smithy/util-defaults-mode-browser": "^4.3.34",
264735
- "@smithy/util-defaults-mode-node": "^4.2.37",
264736
- "@smithy/util-endpoints": "^3.2.9",
264737
- "@smithy/util-middleware": "^4.2.9",
264738
- "@smithy/util-retry": "^4.2.9",
265203
+ "@smithy/util-defaults-mode-browser": "^4.3.36",
265204
+ "@smithy/util-defaults-mode-node": "^4.2.39",
265205
+ "@smithy/util-endpoints": "^3.3.1",
265206
+ "@smithy/util-middleware": "^4.2.10",
265207
+ "@smithy/util-retry": "^4.2.10",
264739
265208
  "@smithy/util-utf8": "^4.2.1",
264740
265209
  tslib: "^2.6.2"
264741
265210
  },
@@ -284726,7 +285195,11 @@ var init_esm3 = __esm({
284726
285195
  #matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
284727
285196
  const firstgs = pattern.indexOf(GLOBSTAR, patternIndex);
284728
285197
  const lastgs = pattern.lastIndexOf(GLOBSTAR);
284729
- const [head2, body, tail] = [
285198
+ const [head2, body, tail] = partial ? [
285199
+ pattern.slice(patternIndex, firstgs),
285200
+ pattern.slice(firstgs + 1),
285201
+ []
285202
+ ] : [
284730
285203
  pattern.slice(patternIndex, firstgs),
284731
285204
  pattern.slice(firstgs + 1, lastgs),
284732
285205
  pattern.slice(lastgs + 1)
@@ -284763,7 +285236,7 @@ var init_esm3 = __esm({
284763
285236
  return false;
284764
285237
  }
284765
285238
  }
284766
- return sawSome;
285239
+ return partial || sawSome;
284767
285240
  }
284768
285241
  const bodySegments = [[[], 0]];
284769
285242
  let currentBody = bodySegments[0];
@@ -284812,7 +285285,7 @@ var init_esm3 = __esm({
284812
285285
  }
284813
285286
  fileIndex++;
284814
285287
  }
284815
- return null;
285288
+ return partial || null;
284816
285289
  }
284817
285290
  #matchOne(file, pattern, partial, fileIndex, patternIndex) {
284818
285291
  let fi;
@@ -327296,6 +327769,15 @@ function normalizeJsonQuotes(str) {
327296
327769
  }
327297
327770
  return result;
327298
327771
  }
327772
+ function isCodeBlockEmbeddedInDocument(text, match2) {
327773
+ const beforeBlock = text.substring(0, match2.index).trim();
327774
+ const afterBlock = text.substring(match2.index + match2[0].length).trim();
327775
+ const hasMarkdownHeadings = /^#{1,6}\s/m.test(beforeBlock) || /^#{1,6}\s/m.test(afterBlock);
327776
+ if (hasMarkdownHeadings) {
327777
+ return true;
327778
+ }
327779
+ return false;
327780
+ }
327299
327781
  function cleanSchemaResponse(response) {
327300
327782
  if (!response || typeof response !== "string") {
327301
327783
  return response;
@@ -327315,11 +327797,11 @@ function cleanSchemaResponse(response) {
327315
327797
  return cleanSchemaResponse(innerContent);
327316
327798
  }
327317
327799
  const jsonBlockMatch = trimmed.match(/```json\s*\n([\s\S]*?)\n```/);
327318
- if (jsonBlockMatch) {
327800
+ if (jsonBlockMatch && !isCodeBlockEmbeddedInDocument(trimmed, jsonBlockMatch)) {
327319
327801
  return normalizeJsonQuotes(jsonBlockMatch[1].trim());
327320
327802
  }
327321
327803
  const anyBlockMatch = trimmed.match(/```\s*\n([{\[][\s\S]*?[}\]])\s*```/);
327322
- if (anyBlockMatch) {
327804
+ if (anyBlockMatch && !isCodeBlockEmbeddedInDocument(trimmed, anyBlockMatch)) {
327323
327805
  return normalizeJsonQuotes(anyBlockMatch[1].trim());
327324
327806
  }
327325
327807
  const codeBlockPatterns = [
@@ -327328,7 +327810,7 @@ function cleanSchemaResponse(response) {
327328
327810
  ];
327329
327811
  for (const pattern of codeBlockPatterns) {
327330
327812
  const match2 = trimmed.match(pattern);
327331
- if (match2) {
327813
+ if (match2 && !isCodeBlockEmbeddedInDocument(trimmed, match2)) {
327332
327814
  return normalizeJsonQuotes(match2[1].trim());
327333
327815
  }
327334
327816
  }
@@ -327339,7 +327821,7 @@ function cleanSchemaResponse(response) {
327339
327821
  }
327340
327822
  const codeBlockStartPattern = /```(?:json)?\s*\n?\s*([{\[])/;
327341
327823
  const codeBlockMatch = trimmed.match(codeBlockStartPattern);
327342
- if (codeBlockMatch) {
327824
+ if (codeBlockMatch && !isCodeBlockEmbeddedInDocument(trimmed, codeBlockMatch)) {
327343
327825
  const startIndex = codeBlockMatch.index + codeBlockMatch[0].length - 1;
327344
327826
  const openChar = codeBlockMatch[1];
327345
327827
  const closeChar = openChar === "{" ? "}" : "]";
@@ -349037,6 +349519,10 @@ function parseSimpleCommand(command) {
349037
349519
  // Logical OR
349038
349520
  /(?<!\\);/,
349039
349521
  // Command separator (but not escaped \;)
349522
+ /\n/,
349523
+ // Newline command separator (multi-line commands)
349524
+ /\r/,
349525
+ // Carriage return (CRLF line endings)
349040
349526
  /&$/,
349041
349527
  // Background execution
349042
349528
  /\$\(/,
@@ -349143,6 +349629,8 @@ function isComplexPattern(pattern) {
349143
349629
  // Logical OR
349144
349630
  /;/,
349145
349631
  // Command separator
349632
+ /\n/,
349633
+ // Newline command separator
349146
349634
  /&$/,
349147
349635
  // Background execution
349148
349636
  /\$\(/,
@@ -349515,6 +350003,26 @@ var init_bashPermissions = __esm({
349515
350003
  i5++;
349516
350004
  continue;
349517
350005
  }
350006
+ if (char === "\n" || char === "\r" && nextChar === "\n") {
350007
+ if (current2.trim()) {
350008
+ components.push(current2.trim());
350009
+ }
350010
+ current2 = "";
350011
+ if (char === "\r") {
350012
+ i5 += 2;
350013
+ } else {
350014
+ i5++;
350015
+ }
350016
+ continue;
350017
+ }
350018
+ if (char === "\r") {
350019
+ if (current2.trim()) {
350020
+ components.push(current2.trim());
350021
+ }
350022
+ current2 = "";
350023
+ i5++;
350024
+ continue;
350025
+ }
349518
350026
  }
349519
350027
  current2 += char;
349520
350028
  i5++;
@@ -394355,7 +394863,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"100":"Continue","101":"Switching Pro
394355
394863
  /***/ ((module) => {
394356
394864
 
394357
394865
  "use strict";
394358
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.144","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-rc259","@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"]}}');
394866
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.145","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-rc260","@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"]}}');
394359
394867
 
394360
394868
  /***/ })
394361
394869