@probelabs/visor 0.1.174 → 0.1.175

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 (84) hide show
  1. package/README.md +3 -2
  2. package/dist/cli-main.d.ts.map +1 -1
  3. package/dist/docs/guides/tdd-assistant-workflows.md +519 -0
  4. package/dist/docs/testing/dsl-reference.md +93 -0
  5. package/dist/examples/lifecycle-hooks.tests.yaml +62 -0
  6. package/dist/generated/config-schema.d.ts +28 -7
  7. package/dist/generated/config-schema.d.ts.map +1 -1
  8. package/dist/generated/config-schema.json +31 -7
  9. package/dist/index.js +331 -26
  10. package/dist/output/traces/{run-2026-03-09T15-44-30-340Z.ndjson → run-2026-03-09T18-49-07-663Z.ndjson} +84 -84
  11. package/dist/output/traces/{run-2026-03-09T15-45-10-778Z.ndjson → run-2026-03-09T18-49-46-345Z.ndjson} +1917 -1901
  12. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  13. package/dist/providers/mcp-custom-sse-server.d.ts +4 -0
  14. package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
  15. package/dist/sdk/{a2a-frontend-5L6H7ZVF.mjs → a2a-frontend-ORLAU5GK.mjs} +2 -2
  16. package/dist/sdk/{check-provider-registry-UPQNHHFF.mjs → check-provider-registry-7JPPJHVM.mjs} +3 -3
  17. package/dist/sdk/{check-provider-registry-YVQI4IOR.mjs → check-provider-registry-O36CQEGD.mjs} +3 -3
  18. package/dist/sdk/{check-provider-registry-UM762L7S.mjs → check-provider-registry-QCDV3SI6.mjs} +6 -6
  19. package/dist/sdk/{chunk-ZI3SEHWA.mjs → chunk-4FGX4SA6.mjs} +2 -2
  20. package/dist/sdk/{chunk-ZI3SEHWA.mjs.map → chunk-4FGX4SA6.mjs.map} +1 -1
  21. package/dist/sdk/{chunk-2PL2YH3B.mjs → chunk-FZPCP444.mjs} +153 -14
  22. package/dist/sdk/chunk-FZPCP444.mjs.map +1 -0
  23. package/dist/sdk/{chunk-UTBSBJFV.mjs → chunk-HNK5ZJ2L.mjs} +2 -2
  24. package/dist/sdk/{chunk-W4KCJM6J.mjs → chunk-MLXGCLZJ.mjs} +29 -8
  25. package/dist/sdk/chunk-MLXGCLZJ.mjs.map +1 -0
  26. package/dist/sdk/{chunk-YEARBXYT.mjs → chunk-QAO73GUX.mjs} +3 -3
  27. package/dist/sdk/{chunk-I6GKXMQ5.mjs → chunk-TAK5HLAR.mjs} +153 -14
  28. package/dist/sdk/chunk-TAK5HLAR.mjs.map +1 -0
  29. package/dist/sdk/{chunk-EP7PQ4IX.mjs → chunk-YVVOG7RP.mjs} +161 -22
  30. package/dist/sdk/chunk-YVVOG7RP.mjs.map +1 -0
  31. package/dist/sdk/{config-BVL3KFMB.mjs → config-4JMBJKWS.mjs} +2 -2
  32. package/dist/sdk/{failure-condition-evaluator-4O6BTC4Q.mjs → failure-condition-evaluator-RM5JJS4Q.mjs} +3 -3
  33. package/dist/sdk/{github-frontend-UXL73NKB.mjs → github-frontend-O5IAWXL5.mjs} +3 -3
  34. package/dist/sdk/{host-KJTXX76P.mjs → host-WTJBWO4T.mjs} +3 -3
  35. package/dist/sdk/{routing-AWYB2YX3.mjs → routing-AWOHU2WP.mjs} +4 -4
  36. package/dist/sdk/{schedule-tool-UMDRCNO5.mjs → schedule-tool-DF5WUVYV.mjs} +3 -3
  37. package/dist/sdk/{schedule-tool-SGCYDSHL.mjs → schedule-tool-L5G2BRIG.mjs} +6 -6
  38. package/dist/sdk/{schedule-tool-IEY2CFLU.mjs → schedule-tool-XVSYLH4Z.mjs} +3 -3
  39. package/dist/sdk/{schedule-tool-handler-5EPTHBLS.mjs → schedule-tool-handler-CFMFHDUL.mjs} +3 -3
  40. package/dist/sdk/{schedule-tool-handler-HMEGLYJF.mjs → schedule-tool-handler-JGWA4N3C.mjs} +3 -3
  41. package/dist/sdk/{schedule-tool-handler-5QVUZ5EZ.mjs → schedule-tool-handler-UJ4RFTW2.mjs} +6 -6
  42. package/dist/sdk/sdk.d.mts +9 -1
  43. package/dist/sdk/sdk.d.ts +9 -1
  44. package/dist/sdk/sdk.js +173 -13
  45. package/dist/sdk/sdk.js.map +1 -1
  46. package/dist/sdk/sdk.mjs +5 -5
  47. package/dist/sdk/{trace-helpers-6TEWG7RK.mjs → trace-helpers-4ERTVCZG.mjs} +2 -2
  48. package/dist/sdk/{workflow-check-provider-VJ7VIMCQ.mjs → workflow-check-provider-ETM452BO.mjs} +3 -3
  49. package/dist/sdk/{workflow-check-provider-7VNIO6L5.mjs → workflow-check-provider-I3XLJP6V.mjs} +6 -6
  50. package/dist/sdk/{workflow-check-provider-EWMZEEES.mjs → workflow-check-provider-Z6U7FZAF.mjs} +3 -3
  51. package/dist/test-runner/conversation-sugar.d.ts.map +1 -1
  52. package/dist/test-runner/index.d.ts +19 -0
  53. package/dist/test-runner/index.d.ts.map +1 -1
  54. package/dist/test-runner/validator.d.ts.map +1 -1
  55. package/dist/traces/{run-2026-03-09T15-44-30-340Z.ndjson → run-2026-03-09T18-49-07-663Z.ndjson} +84 -84
  56. package/dist/traces/{run-2026-03-09T15-45-10-778Z.ndjson → run-2026-03-09T18-49-46-345Z.ndjson} +1917 -1901
  57. package/dist/types/config.d.ts +9 -1
  58. package/dist/types/config.d.ts.map +1 -1
  59. package/package.json +1 -1
  60. package/dist/sdk/chunk-2PL2YH3B.mjs.map +0 -1
  61. package/dist/sdk/chunk-EP7PQ4IX.mjs.map +0 -1
  62. package/dist/sdk/chunk-I6GKXMQ5.mjs.map +0 -1
  63. package/dist/sdk/chunk-W4KCJM6J.mjs.map +0 -1
  64. /package/dist/sdk/{a2a-frontend-5L6H7ZVF.mjs.map → a2a-frontend-ORLAU5GK.mjs.map} +0 -0
  65. /package/dist/sdk/{check-provider-registry-UM762L7S.mjs.map → check-provider-registry-7JPPJHVM.mjs.map} +0 -0
  66. /package/dist/sdk/{check-provider-registry-UPQNHHFF.mjs.map → check-provider-registry-O36CQEGD.mjs.map} +0 -0
  67. /package/dist/sdk/{check-provider-registry-YVQI4IOR.mjs.map → check-provider-registry-QCDV3SI6.mjs.map} +0 -0
  68. /package/dist/sdk/{chunk-UTBSBJFV.mjs.map → chunk-HNK5ZJ2L.mjs.map} +0 -0
  69. /package/dist/sdk/{chunk-YEARBXYT.mjs.map → chunk-QAO73GUX.mjs.map} +0 -0
  70. /package/dist/sdk/{config-BVL3KFMB.mjs.map → config-4JMBJKWS.mjs.map} +0 -0
  71. /package/dist/sdk/{failure-condition-evaluator-4O6BTC4Q.mjs.map → failure-condition-evaluator-RM5JJS4Q.mjs.map} +0 -0
  72. /package/dist/sdk/{github-frontend-UXL73NKB.mjs.map → github-frontend-O5IAWXL5.mjs.map} +0 -0
  73. /package/dist/sdk/{host-KJTXX76P.mjs.map → host-WTJBWO4T.mjs.map} +0 -0
  74. /package/dist/sdk/{routing-AWYB2YX3.mjs.map → routing-AWOHU2WP.mjs.map} +0 -0
  75. /package/dist/sdk/{schedule-tool-IEY2CFLU.mjs.map → schedule-tool-DF5WUVYV.mjs.map} +0 -0
  76. /package/dist/sdk/{schedule-tool-SGCYDSHL.mjs.map → schedule-tool-L5G2BRIG.mjs.map} +0 -0
  77. /package/dist/sdk/{schedule-tool-UMDRCNO5.mjs.map → schedule-tool-XVSYLH4Z.mjs.map} +0 -0
  78. /package/dist/sdk/{schedule-tool-handler-5EPTHBLS.mjs.map → schedule-tool-handler-CFMFHDUL.mjs.map} +0 -0
  79. /package/dist/sdk/{schedule-tool-handler-5QVUZ5EZ.mjs.map → schedule-tool-handler-JGWA4N3C.mjs.map} +0 -0
  80. /package/dist/sdk/{schedule-tool-handler-HMEGLYJF.mjs.map → schedule-tool-handler-UJ4RFTW2.mjs.map} +0 -0
  81. /package/dist/sdk/{trace-helpers-6TEWG7RK.mjs.map → trace-helpers-4ERTVCZG.mjs.map} +0 -0
  82. /package/dist/sdk/{workflow-check-provider-7VNIO6L5.mjs.map → workflow-check-provider-ETM452BO.mjs.map} +0 -0
  83. /package/dist/sdk/{workflow-check-provider-EWMZEEES.mjs.map → workflow-check-provider-I3XLJP6V.mjs.map} +0 -0
  84. /package/dist/sdk/{workflow-check-provider-VJ7VIMCQ.mjs.map → workflow-check-provider-Z6U7FZAF.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.174';
2
+ process.env.VISOR_VERSION = '0.1.175';
3
3
  process.env.PROBE_VERSION = '0.6.0-rc291';
4
- process.env.VISOR_COMMIT_SHA = 'e8809d0dd7ef9584a6c687826df911bbc12d7fbd';
5
- process.env.VISOR_COMMIT_SHORT = 'e8809d0d';
4
+ process.env.VISOR_COMMIT_SHA = '5b303b06870720f90057ff3f58f0e72f34bf80cb';
5
+ process.env.VISOR_COMMIT_SHORT = '5b303b06';
6
6
  /******/ (() => { // webpackBootstrap
7
7
  /******/ var __webpack_modules__ = ({
8
8
 
@@ -303441,6 +303441,7 @@ async function handleTestCommand(argv) {
303441
303441
  const flagsWithValues = new Set([
303442
303442
  '--config',
303443
303443
  '--only',
303444
+ '--case',
303444
303445
  '--json',
303445
303446
  '--report',
303446
303447
  '--summary',
@@ -303470,7 +303471,7 @@ async function handleTestCommand(argv) {
303470
303471
  break;
303471
303472
  }
303472
303473
  }
303473
- const only = getArg('--only');
303474
+ const only = getArg('--only') || getArg('--case');
303474
303475
  const bail = hasFlag('--bail');
303475
303476
  const noMocks = hasFlag('--no-mocks');
303476
303477
  const noMocksForRaw = getArg('--no-mocks-for');
@@ -314327,7 +314328,7 @@ exports.configSchema = {
314327
314328
  properties: {
314328
314329
  type: {
314329
314330
  type: 'string',
314330
- enum: ['command', 'api', 'workflow'],
314331
+ enum: ['command', 'api', 'workflow', 'http_client'],
314331
314332
  description: "Tool implementation type (defaults to 'command')",
314332
314333
  },
314333
314334
  name: {
@@ -314524,6 +314525,27 @@ exports.configSchema = {
314524
314525
  type: 'number',
314525
314526
  description: 'Alias for requestTimeoutMs (snake_case)',
314526
314527
  },
314528
+ base_url: {
314529
+ type: 'string',
314530
+ description: 'Base URL for HTTP client tools',
314531
+ },
314532
+ auth: {
314533
+ type: 'object',
314534
+ properties: {
314535
+ type: {
314536
+ type: 'string',
314537
+ },
314538
+ token: {
314539
+ type: 'string',
314540
+ },
314541
+ },
314542
+ required: ['type'],
314543
+ additionalProperties: {},
314544
+ description: 'Authentication config for HTTP client tools',
314545
+ patternProperties: {
314546
+ '^x-': {},
314547
+ },
314548
+ },
314527
314549
  workflow: {
314528
314550
  type: 'string',
314529
314551
  description: "Workflow ID (registry lookup) or file path (for type: 'workflow')",
@@ -315063,7 +315085,7 @@ exports.configSchema = {
315063
315085
  description: 'Arguments/inputs for the workflow',
315064
315086
  },
315065
315087
  overrides: {
315066
- $ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833%3E%3E',
315088
+ $ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090%3E%3E',
315067
315089
  description: 'Override specific step configurations in the workflow',
315068
315090
  },
315069
315091
  output_mapping: {
@@ -315079,7 +315101,7 @@ exports.configSchema = {
315079
315101
  description: 'Config file path - alternative to workflow ID (loads a Visor config file as workflow)',
315080
315102
  },
315081
315103
  workflow_overrides: {
315082
- $ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833%3E%3E',
315104
+ $ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090%3E%3E',
315083
315105
  description: 'Alias for overrides - workflow step overrides (backward compatibility)',
315084
315106
  },
315085
315107
  ref: {
@@ -315781,7 +315803,7 @@ exports.configSchema = {
315781
315803
  description: 'Custom output name (defaults to workflow name)',
315782
315804
  },
315783
315805
  overrides: {
315784
- $ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833%3E%3E',
315806
+ $ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090%3E%3E',
315785
315807
  description: 'Step overrides',
315786
315808
  },
315787
315809
  output_mapping: {
@@ -315796,13 +315818,13 @@ exports.configSchema = {
315796
315818
  '^x-': {},
315797
315819
  },
315798
315820
  },
315799
- 'Record<string,Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833>>': {
315821
+ 'Record<string,Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090>>': {
315800
315822
  type: 'object',
315801
315823
  additionalProperties: {
315802
- $ref: '#/definitions/Partial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833%3E',
315824
+ $ref: '#/definitions/Partial%3Cinterface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090%3E',
315803
315825
  },
315804
315826
  },
315805
- 'Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-56833>': {
315827
+ 'Partial<interface-src_types_config.ts-14017-28611-src_types_config.ts-0-57090>': {
315806
315828
  type: 'object',
315807
315829
  additionalProperties: false,
315808
315830
  },
@@ -325781,12 +325803,14 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
325781
325803
  break; // Only support one custom tools server per check
325782
325804
  }
325783
325805
  }
325784
- // Option 4: Extract workflow and tool entries from ai_mcp_servers/ai_mcp_servers_js
325806
+ // Option 4: Extract workflow, tool, and http_client entries from ai_mcp_servers/ai_mcp_servers_js
325785
325807
  // Unified format:
325786
325808
  // { workflow: 'name', inputs: {...} } → workflow tool
325787
325809
  // { tool: 'name' } → custom tool from tools: section or built-in (e.g., 'schedule')
325810
+ // { type: 'http_client', base_url: '...', ... } → HTTP client tool (REST API proxy)
325788
325811
  const workflowEntriesFromMcp = [];
325789
325812
  const toolEntriesFromMcp = [];
325813
+ const httpClientEntriesFromMcp = [];
325790
325814
  const mcpEntriesToRemove = [];
325791
325815
  for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
325792
325816
  const cfg = serverConfig;
@@ -325801,6 +325825,12 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
325801
325825
  mcpEntriesToRemove.push(serverName);
325802
325826
  logger_1.logger.debug(`[AICheckProvider] Extracted workflow tool '${serverName}' (workflow=${cfg.workflow}) from ai_mcp_servers`);
325803
325827
  }
325828
+ else if (cfg.type === 'http_client' && (cfg.base_url || cfg.url)) {
325829
+ // HTTP client tool entry — REST API proxy exposed as an MCP tool
325830
+ httpClientEntriesFromMcp.push({ name: serverName, config: cfg });
325831
+ mcpEntriesToRemove.push(serverName);
325832
+ logger_1.logger.debug(`[AICheckProvider] Extracted http_client tool '${serverName}' (base_url=${cfg.base_url || cfg.url}) from ai_mcp_servers`);
325833
+ }
325804
325834
  else if (cfg.tool && typeof cfg.tool === 'string') {
325805
325835
  // Custom tool or built-in tool entry
325806
325836
  toolEntriesFromMcp.push(cfg.tool);
@@ -325859,8 +325889,10 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
325859
325889
  }
325860
325890
  // Legacy support: enable_scheduler: true also enables the schedule tool
325861
325891
  const scheduleToolEnabled = scheduleToolRequested || (config.ai?.enable_scheduler === true && !config.ai?.disableTools);
325862
- if ((customToolsToLoad.length > 0 || scheduleToolEnabled) &&
325863
- (customToolsServerName || scheduleToolEnabled) &&
325892
+ if ((customToolsToLoad.length > 0 ||
325893
+ scheduleToolEnabled ||
325894
+ httpClientEntriesFromMcp.length > 0) &&
325895
+ (customToolsServerName || scheduleToolEnabled || httpClientEntriesFromMcp.length > 0) &&
325864
325896
  !config.ai?.disableTools) {
325865
325897
  if (!customToolsServerName) {
325866
325898
  customToolsServerName = '__tools__';
@@ -325896,6 +325928,49 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
325896
325928
  customTools.set(scheduleTool.name, scheduleTool);
325897
325929
  logger_1.logger.debug(`[AICheckProvider] Added built-in schedule tool`);
325898
325930
  }
325931
+ // Add http_client tools extracted from ai_mcp_servers
325932
+ for (const entry of httpClientEntriesFromMcp) {
325933
+ const httpTool = {
325934
+ name: entry.name,
325935
+ type: 'http_client',
325936
+ description: entry.config.description ||
325937
+ `Call ${entry.name} HTTP API (base: ${entry.config.base_url || entry.config.url})`,
325938
+ base_url: (entry.config.base_url || entry.config.url),
325939
+ auth: entry.config.auth,
325940
+ headers: entry.config.headers,
325941
+ timeout: entry.config.timeout || 30000,
325942
+ inputSchema: {
325943
+ type: 'object',
325944
+ properties: {
325945
+ path: {
325946
+ type: 'string',
325947
+ description: 'API path (e.g. /jobs, /candidates/{id})',
325948
+ },
325949
+ method: {
325950
+ type: 'string',
325951
+ description: 'HTTP method (default: GET)',
325952
+ enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
325953
+ },
325954
+ query: {
325955
+ type: 'object',
325956
+ description: 'Query string parameters',
325957
+ additionalProperties: { type: 'string' },
325958
+ },
325959
+ body: {
325960
+ type: 'object',
325961
+ description: 'Request body for POST/PUT/PATCH',
325962
+ },
325963
+ },
325964
+ required: ['path'],
325965
+ },
325966
+ };
325967
+ customTools.set(entry.name, httpTool);
325968
+ logger_1.logger.debug(`[AICheckProvider] Added http_client tool '${entry.name}' (base_url=${httpTool.base_url})`);
325969
+ }
325970
+ // Ensure SSE server is created when http_client tools are present
325971
+ if (httpClientEntriesFromMcp.length > 0 && !customToolsServerName) {
325972
+ customToolsServerName = '__tools__';
325973
+ }
325899
325974
  if (customTools.size > 0) {
325900
325975
  const sessionId = config.checkName || `ai-check-${Date.now()}`;
325901
325976
  const debug = aiConfig.debug || process.env.VISOR_DEBUG === 'true';
@@ -333737,6 +333812,13 @@ const workflow_registry_1 = __nccwpck_require__(82824);
333737
333812
  const schedule_tool_1 = __nccwpck_require__(13395);
333738
333813
  // Legacy Slack-specific imports for backwards compatibility
333739
333814
  const schedule_tool_handler_1 = __nccwpck_require__(28883);
333815
+ const env_resolver_1 = __nccwpck_require__(58749);
333816
+ /**
333817
+ * Check if a tool definition is an http_client tool
333818
+ */
333819
+ function isHttpClientTool(tool) {
333820
+ return Boolean(tool && tool.type === 'http_client' && (tool.base_url || tool.url));
333821
+ }
333740
333822
  /**
333741
333823
  * SSE-based MCP server that exposes custom tools from YAML configuration
333742
333824
  * Implements the Model Context Protocol over Server-Sent Events
@@ -333775,14 +333857,16 @@ class CustomToolsSSEServer {
333775
333857
  }
333776
333858
  }
333777
333859
  }
333778
- // Second pass: separate workflow tools from regular tools
333860
+ // Second pass: separate workflow and http_client tools from regular tools
333779
333861
  for (const [name, tool] of this.tools.entries()) {
333780
- // Skip workflow tools - they're handled separately
333781
- if (!(0, workflow_tool_executor_1.isWorkflowTool)(tool)) {
333782
- toolsRecord[name] = tool;
333862
+ // Skip workflow and http_client tools - they're handled separately
333863
+ if ((0, workflow_tool_executor_1.isWorkflowTool)(tool) || isHttpClientTool(tool)) {
333864
+ if ((0, workflow_tool_executor_1.isWorkflowTool)(tool)) {
333865
+ workflowToolNames.push(name);
333866
+ }
333783
333867
  }
333784
333868
  else {
333785
- workflowToolNames.push(name);
333869
+ toolsRecord[name] = tool;
333786
333870
  }
333787
333871
  }
333788
333872
  // Warn if workflow tools are present but no context is provided
@@ -334256,7 +334340,14 @@ class CustomToolsSSEServer {
334256
334340
  description: tool.description || `Execute ${tool.name}`,
334257
334341
  inputSchema: normalizeInputSchema(tool.inputSchema),
334258
334342
  }));
334259
- const allTools = [...regularTools, ...workflowTools];
334343
+ const httpClientTools = Array.from(this.tools.values())
334344
+ .filter(isHttpClientTool)
334345
+ .map(tool => ({
334346
+ name: tool.name,
334347
+ description: tool.description || `Call ${tool.name} HTTP API`,
334348
+ inputSchema: normalizeInputSchema(tool.inputSchema),
334349
+ }));
334350
+ const allTools = [...regularTools, ...workflowTools, ...httpClientTools];
334260
334351
  if (this.debug) {
334261
334352
  logger_1.logger.debug(`[CustomToolsSSEServer:${this.sessionId}] Listing ${allTools.length} tools: ${allTools.map(t => t.name).join(', ')}`);
334262
334353
  }
@@ -334378,6 +334469,10 @@ class CustomToolsSSEServer {
334378
334469
  const workflowTool = tool;
334379
334470
  result = await (0, workflow_tool_executor_1.executeWorkflowAsTool)(workflowTool.__workflowId, args, this.workflowContext, workflowTool.__argsOverrides);
334380
334471
  }
334472
+ else if (tool && isHttpClientTool(tool)) {
334473
+ // Execute HTTP client tool — proxy REST API calls
334474
+ result = await this.executeHttpClientTool(tool, args);
334475
+ }
334381
334476
  else {
334382
334477
  // Execute regular custom tool
334383
334478
  result = await this.toolExecutor.execute(toolName, args);
@@ -334442,6 +334537,88 @@ class CustomToolsSSEServer {
334442
334537
  }
334443
334538
  }
334444
334539
  }
334540
+ /**
334541
+ * Execute an http_client tool — proxy REST API calls through the configured base URL.
334542
+ */
334543
+ async executeHttpClientTool(tool, args) {
334544
+ const baseUrl = (tool.base_url || tool.url).replace(/\/+$/, '');
334545
+ const apiPath = args.path || '';
334546
+ const method = (args.method || 'GET').toUpperCase();
334547
+ const queryParams = args.query || {};
334548
+ const body = args.body;
334549
+ const toolHeaders = tool.headers || {};
334550
+ const timeout = tool.timeout || 30000;
334551
+ // Build full URL
334552
+ let url = apiPath.startsWith('http') ? apiPath : `${baseUrl}/${apiPath.replace(/^\/+/, '')}`;
334553
+ // Append query parameters
334554
+ if (Object.keys(queryParams).length > 0) {
334555
+ const qs = new URLSearchParams(queryParams).toString();
334556
+ url += `${url.includes('?') ? '&' : '?'}${qs}`;
334557
+ }
334558
+ // Resolve environment variables in headers
334559
+ const resolvedHeaders = {};
334560
+ for (const [key, value] of Object.entries(toolHeaders)) {
334561
+ resolvedHeaders[key] = String(env_resolver_1.EnvironmentResolver.resolveValue(value));
334562
+ }
334563
+ // Handle auth
334564
+ if (tool.auth) {
334565
+ const authType = tool.auth.type;
334566
+ if (authType === 'bearer' && tool.auth.token) {
334567
+ const token = String(env_resolver_1.EnvironmentResolver.resolveValue(tool.auth.token));
334568
+ resolvedHeaders['Authorization'] = `Bearer ${token}`;
334569
+ }
334570
+ }
334571
+ if (this.debug) {
334572
+ logger_1.logger.debug(`[CustomToolsSSEServer:${this.sessionId}] HTTP client: ${method} ${url}`);
334573
+ }
334574
+ const controller = new AbortController();
334575
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
334576
+ try {
334577
+ const requestOptions = {
334578
+ method,
334579
+ headers: resolvedHeaders,
334580
+ signal: controller.signal,
334581
+ };
334582
+ if (method !== 'GET' && body) {
334583
+ requestOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
334584
+ if (!resolvedHeaders['Content-Type'] && !resolvedHeaders['content-type']) {
334585
+ resolvedHeaders['Content-Type'] = 'application/json';
334586
+ }
334587
+ }
334588
+ const response = await fetch(url, requestOptions);
334589
+ clearTimeout(timeoutId);
334590
+ if (!response.ok) {
334591
+ let errorBody = '';
334592
+ try {
334593
+ errorBody = await response.text();
334594
+ }
334595
+ catch { }
334596
+ throw new Error(`HTTP ${response.status}: ${response.statusText}${errorBody ? ` - ${errorBody.substring(0, 500)}` : ''}`);
334597
+ }
334598
+ // Parse response
334599
+ const contentType = response.headers.get('content-type');
334600
+ if (contentType && contentType.includes('application/json')) {
334601
+ return await response.json();
334602
+ }
334603
+ const text = await response.text();
334604
+ if (text.trim().startsWith('{') || text.trim().startsWith('[')) {
334605
+ try {
334606
+ return JSON.parse(text);
334607
+ }
334608
+ catch {
334609
+ return text;
334610
+ }
334611
+ }
334612
+ return text;
334613
+ }
334614
+ catch (error) {
334615
+ clearTimeout(timeoutId);
334616
+ if (error instanceof Error && error.name === 'AbortError') {
334617
+ throw new Error(`HTTP client request timed out after ${timeout}ms`);
334618
+ }
334619
+ throw error;
334620
+ }
334621
+ }
334445
334622
  /**
334446
334623
  * Convert a type: 'workflow' tool definition into a WorkflowToolDefinition marker.
334447
334624
  *
@@ -359551,9 +359728,11 @@ function expandConversationToFlow(testCase) {
359551
359728
  flow.push(stage);
359552
359729
  // After this stage, add user message + assumed assistant response to history
359553
359730
  messageHistory.push({ role: 'user', text: turn.text });
359554
- // Look for mock response text to add as assistant message for next turn
359731
+ // Look for mock response text to add as assistant message for next turn.
359732
+ // Record the index so the runner can replace it with the real response in --no-mocks mode.
359555
359733
  const assistantText = extractMockResponseText(turn.mocks);
359556
359734
  if (assistantText) {
359735
+ stage._mockAssistantMsgIndex = messageHistory.length; // index of the assistant msg about to be pushed
359557
359736
  messageHistory.push({ role: 'assistant', text: assistantText });
359558
359737
  }
359559
359738
  }
@@ -361681,6 +361860,31 @@ class VisorTestRunner {
361681
361860
  const pad = Math.max(1, width - title.length - 2);
361682
361861
  return `${char.repeat(2)} ${title} ${char.repeat(pad)}`;
361683
361862
  }
361863
+ /**
361864
+ * Execute a lifecycle hook (shell command). Returns true on success, false on failure.
361865
+ */
361866
+ async runHook(hook, label, cwd) {
361867
+ if (!hook)
361868
+ return { ok: true };
361869
+ const timeoutMs = hook.timeout || 30_000;
361870
+ console.log(this.gray(` ⚙ ${label}: ${hook.exec}`));
361871
+ try {
361872
+ const { execSync } = __nccwpck_require__(35317);
361873
+ execSync(hook.exec, {
361874
+ cwd,
361875
+ stdio: ['ignore', 'pipe', 'pipe'],
361876
+ timeout: timeoutMs,
361877
+ env: { ...process.env },
361878
+ });
361879
+ return { ok: true };
361880
+ }
361881
+ catch (err) {
361882
+ const stderr = err.stderr ? err.stderr.toString().trim() : '';
361883
+ const msg = stderr || err.message || String(err);
361884
+ console.log(this.color(` ✖ ${label} failed: ${msg}`, '31'));
361885
+ return { ok: false, error: `${label} failed: ${msg}` };
361886
+ }
361887
+ }
361684
361888
  // Extracted helper: prepare engine/recorder, prompts/mocks, env, and checksToRun for a single-event case
361685
361889
  setupTestCase(_case, cfg, defaultStrict, defaultPromptCap, ghRec, defaultIncludeTags, defaultExcludeTags, noMocks, noMocksFor) {
361686
361890
  const name = _case.name || '(unnamed)';
@@ -362082,6 +362286,7 @@ class VisorTestRunner {
362082
362286
  extends: doc.extends,
362083
362287
  tests: {
362084
362288
  defaults: tests.defaults || {},
362289
+ hooks: tests.hooks || undefined,
362085
362290
  fixtures: tests.fixtures || [],
362086
362291
  cases: tests.cases,
362087
362292
  },
@@ -362271,6 +362476,18 @@ class VisorTestRunner {
362271
362476
  }
362272
362477
  }
362273
362478
  catch { }
362479
+ // Lifecycle hooks
362480
+ const suiteHooks = suite.tests.hooks || {};
362481
+ const suiteCwd = path_1.default.dirname(testsPath);
362482
+ const beforeAllResult = await this.runHook(suiteHooks.before_all, 'before_all', suiteCwd);
362483
+ if (!beforeAllResult.ok) {
362484
+ // Skip all cases when before_all fails
362485
+ for (const c of selected) {
362486
+ caseResults.push({ name: c.name, passed: false, errors: [beforeAllResult.error] });
362487
+ }
362488
+ clearInterval(__keepAlive);
362489
+ return { failures: selected.length, results: caseResults };
362490
+ }
362274
362491
  const runOne = async (_caseOrig) => {
362275
362492
  // Expand conversation sugar to flow stages before any processing
362276
362493
  const { expandConversationToFlow } = __nccwpck_require__(15921);
@@ -362290,11 +362507,32 @@ class VisorTestRunner {
362290
362507
  caseResults.push({ name: _case.name, passed: true, errors: [] });
362291
362508
  return { name: _case.name, failed: 0 };
362292
362509
  }
362510
+ // Run before_each (suite-level) and before (case-level) hooks
362511
+ const caseHooks = _case.hooks || {};
362512
+ const beforeEachRes = await this.runHook(suiteHooks.before_each, 'before_each', suiteCwd);
362513
+ if (!beforeEachRes.ok) {
362514
+ caseResults.push({ name: _case.name, passed: false, errors: [beforeEachRes.error] });
362515
+ return { name: _case.name, failed: 1 };
362516
+ }
362517
+ const beforeRes = await this.runHook(caseHooks.before, `before (${_case.name})`, suiteCwd);
362518
+ if (!beforeRes.ok) {
362519
+ // after_each still runs even if before fails
362520
+ await this.runHook(suiteHooks.after_each, 'after_each', suiteCwd);
362521
+ caseResults.push({ name: _case.name, passed: false, errors: [beforeRes.error] });
362522
+ return { name: _case.name, failed: 1 };
362523
+ }
362293
362524
  if (Array.isArray(_case.flow) && _case.flow.length > 0) {
362294
- const flowRes = await this.runFlowCase(_case, cfg, defaultStrict, options.bail || false, defaultPromptCap, stageFilter, noMocksMode);
362295
- const failed = flowRes.failures;
362296
- caseResults.push({ name: _case.name, passed: failed === 0, stages: flowRes.stages });
362297
- return { name: _case.name, failed };
362525
+ try {
362526
+ const flowRes = await this.runFlowCase(_case, cfg, defaultStrict, options.bail || false, defaultPromptCap, stageFilter, noMocksMode);
362527
+ const failed = flowRes.failures;
362528
+ caseResults.push({ name: _case.name, passed: failed === 0, stages: flowRes.stages });
362529
+ return { name: _case.name, failed };
362530
+ }
362531
+ finally {
362532
+ // after (case-level) and after_each (suite-level) always run
362533
+ await this.runHook(caseHooks.after, `after (${_case.name})`, suiteCwd);
362534
+ await this.runHook(suiteHooks.after_each, 'after_each', suiteCwd);
362535
+ }
362298
362536
  }
362299
362537
  // Per-case AI override: include code context when requested
362300
362538
  const suiteDefaults = this.suiteDefaults || {};
@@ -362523,6 +362761,9 @@ class VisorTestRunner {
362523
362761
  return { name: _case.name, failed: 1 };
362524
362762
  }
362525
362763
  finally {
362764
+ // after (case-level) and after_each (suite-level) always run
362765
+ await this.runHook(caseHooks.after, `after (${_case.name})`, suiteCwd);
362766
+ await this.runHook(suiteHooks.after_each, 'after_each', suiteCwd);
362526
362767
  try {
362527
362768
  // Restore env for this case using original setup
362528
362769
  setup.restoreEnv();
@@ -362553,6 +362794,8 @@ class VisorTestRunner {
362553
362794
  };
362554
362795
  await Promise.all(Array.from({ length: workers }, runWorker));
362555
362796
  }
362797
+ // after_all always runs (like finally), even if tests failed
362798
+ await this.runHook(suiteHooks.after_all, 'after_all', suiteCwd);
362556
362799
  // Summary (suppressible for embedded runs)
362557
362800
  const failedCases = caseResults.filter(r => !r.passed);
362558
362801
  const passedCases = caseResults.filter(r => r.passed);
@@ -362761,6 +363004,24 @@ class VisorTestRunner {
362761
363004
  const defaultExcludeTags = parseTags(suiteDefaults?.exclude_tags);
362762
363005
  const stageRunner = new flow_stage_1.FlowStage(flowName, engine, recorder, cfg, prompts, promptCap, this.mapEventFromFixtureName.bind(this), this.computeChecksToRun.bind(this), this.printStageHeader.bind(this), this.printSelectedChecks.bind(this), this.warnUnmockedProviders.bind(this), defaultIncludeTags, defaultExcludeTags, (suiteDefaults.frontends || undefined), noMocks, suiteDefaults.llm_judge || undefined, cumulativeOutputHistory);
362763
363006
  const outcome = await stageRunner.run(stage, flowCase, strict);
363007
+ // In conversation sugar + --no-mocks: replace mock assistant text in
363008
+ // subsequent stages' message history with the real AI response.
363009
+ if (noMocks &&
363010
+ flowCase._conversationSugar &&
363011
+ typeof stage._mockAssistantMsgIndex === 'number') {
363012
+ const realText = this.extractLastResponseText(cumulativeOutputHistory);
363013
+ if (realText) {
363014
+ for (let j = i + 1; j < flowCase.flow.length; j++) {
363015
+ const nextMsgs = flowCase.flow[j]?.execution_context?.conversation?.messages;
363016
+ if (Array.isArray(nextMsgs) && nextMsgs[stage._mockAssistantMsgIndex]) {
363017
+ nextMsgs[stage._mockAssistantMsgIndex] = {
363018
+ ...nextMsgs[stage._mockAssistantMsgIndex],
363019
+ text: realText,
363020
+ };
363021
+ }
363022
+ }
363023
+ }
363024
+ }
362764
363025
  const expect = stage.expect || {};
362765
363026
  if (outcome.stats)
362766
363027
  this.printCoverage(outcome.name, outcome.stats, expect);
@@ -362805,6 +363066,21 @@ class VisorTestRunner {
362805
363066
  console.log(`${this.tagFail ? this.tagFail() : '❌ FAIL'} ${flowName} (${failures} stage error${failures > 1 ? 's' : ''})`);
362806
363067
  return { failures, stages: stagesSummary };
362807
363068
  }
363069
+ /**
363070
+ * Extract the last response text from cumulative output history (for conversation sugar).
363071
+ * Looks for 'chat' step outputs with a 'text' field.
363072
+ */
363073
+ extractLastResponseText(history) {
363074
+ // The assistant workflow emits output on the 'chat' step with a 'text' field
363075
+ const chatOutputs = history['chat'];
363076
+ if (!Array.isArray(chatOutputs) || chatOutputs.length === 0)
363077
+ return undefined;
363078
+ const last = chatOutputs[chatOutputs.length - 1];
363079
+ if (last && typeof last === 'object' && typeof last.text === 'string') {
363080
+ return last.text;
363081
+ }
363082
+ return undefined;
363083
+ }
362808
363084
  mapEventFromFixtureName(name) {
362809
363085
  if (!name)
362810
363086
  return 'manual';
@@ -363662,6 +363938,7 @@ const schema = {
363662
363938
  },
363663
363939
  },
363664
363940
  },
363941
+ hooks: { $ref: '#/$defs/suiteHooks' },
363665
363942
  fixtures: { type: 'array' },
363666
363943
  cases: {
363667
363944
  type: 'array',
@@ -363673,6 +363950,33 @@ const schema = {
363673
363950
  },
363674
363951
  required: ['tests'],
363675
363952
  $defs: {
363953
+ hookDef: {
363954
+ type: 'object',
363955
+ additionalProperties: false,
363956
+ properties: {
363957
+ exec: { type: 'string' },
363958
+ timeout: { type: 'number' },
363959
+ },
363960
+ required: ['exec'],
363961
+ },
363962
+ suiteHooks: {
363963
+ type: 'object',
363964
+ additionalProperties: false,
363965
+ properties: {
363966
+ before_all: { $ref: '#/$defs/hookDef' },
363967
+ after_all: { $ref: '#/$defs/hookDef' },
363968
+ before_each: { $ref: '#/$defs/hookDef' },
363969
+ after_each: { $ref: '#/$defs/hookDef' },
363970
+ },
363971
+ },
363972
+ caseHooks: {
363973
+ type: 'object',
363974
+ additionalProperties: false,
363975
+ properties: {
363976
+ before: { $ref: '#/$defs/hookDef' },
363977
+ after: { $ref: '#/$defs/hookDef' },
363978
+ },
363979
+ },
363676
363980
  fixtureRef: {
363677
363981
  oneOf: [
363678
363982
  { type: 'string' },
@@ -363751,6 +364055,7 @@ const schema = {
363751
364055
  },
363752
364056
  // Workflow testing: input values to pass to the workflow
363753
364057
  workflow_input: { type: 'object' },
364058
+ hooks: { $ref: '#/$defs/caseHooks' },
363754
364059
  expect: { $ref: '#/$defs/expectBlock' },
363755
364060
  // Flow cases
363756
364061
  flow: {
@@ -608370,7 +608675,7 @@ module.exports = /*#__PURE__*/JSON.parse('["aaa","aarp","abb","abbott","abbvie",
608370
608675
  /***/ ((module) => {
608371
608676
 
608372
608677
  "use strict";
608373
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.174","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","@grammyjs/runner":"^2.0.3","@modelcontextprotocol/sdk":"^1.25.3","@nyariv/sandboxjs":"github:probelabs/SandboxJS#23c4bb611f7d05f3cb8c523917b5f57103e48108","@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/api-logs":"^0.203.0","@opentelemetry/core":"^1.30.1","@opentelemetry/exporter-logs-otlp-http":"^0.203.0","@opentelemetry/exporter-metrics-otlp-http":"^0.203.0","@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-logs":"^0.203.0","@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-rc291","@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","botbuilder":"^4.23.3","botframework-connector":"^4.23.3","cli-table3":"^0.6.5","commander":"^14.0.0","deepmerge":"^4.3.1","dotenv":"^17.2.3","grammy":"^1.41.1","ignore":"^7.0.5","imapflow":"^1.2.12","js-yaml":"^4.1.0","jsonpath-plus":"^10.4.0","liquidjs":"^10.21.1","mailparser":"^3.9.3","minimatch":"^10.2.2","node-cron":"^3.0.3","nodemailer":"^8.0.1","open":"^9.1.0","resend":"^6.9.3","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/mailparser":"^3.4.6","@types/node":"^24.3.0","@types/node-cron":"^3.0.11","@types/nodemailer":"^7.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"]}}');
608678
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.175","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","@grammyjs/runner":"^2.0.3","@modelcontextprotocol/sdk":"^1.25.3","@nyariv/sandboxjs":"github:probelabs/SandboxJS#23c4bb611f7d05f3cb8c523917b5f57103e48108","@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/api-logs":"^0.203.0","@opentelemetry/core":"^1.30.1","@opentelemetry/exporter-logs-otlp-http":"^0.203.0","@opentelemetry/exporter-metrics-otlp-http":"^0.203.0","@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-logs":"^0.203.0","@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-rc291","@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","botbuilder":"^4.23.3","botframework-connector":"^4.23.3","cli-table3":"^0.6.5","commander":"^14.0.0","deepmerge":"^4.3.1","dotenv":"^17.2.3","grammy":"^1.41.1","ignore":"^7.0.5","imapflow":"^1.2.12","js-yaml":"^4.1.0","jsonpath-plus":"^10.4.0","liquidjs":"^10.21.1","mailparser":"^3.9.3","minimatch":"^10.2.2","node-cron":"^3.0.3","nodemailer":"^8.0.1","open":"^9.1.0","resend":"^6.9.3","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/mailparser":"^3.4.6","@types/node":"^24.3.0","@types/node-cron":"^3.0.11","@types/nodemailer":"^7.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"]}}');
608374
608679
 
608375
608680
  /***/ })
608376
608681