@probelabs/visor 0.1.165 → 0.1.166
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.
- package/dist/index.js +525 -120
- package/dist/output/traces/{run-2026-03-06T06-08-10-897Z.ndjson → run-2026-03-06T13-08-34-152Z.ndjson} +84 -84
- package/dist/output/traces/{run-2026-03-06T06-08-55-016Z.ndjson → run-2026-03-06T13-09-10-593Z.ndjson} +1894 -1894
- package/dist/pr-analyzer.d.ts +2 -1
- package/dist/pr-analyzer.d.ts.map +1 -1
- package/dist/providers/http-client-provider.d.ts.map +1 -1
- package/dist/sdk/{check-provider-registry-6P2KJ423.mjs → check-provider-registry-TGPICTHD.mjs} +5 -5
- package/dist/sdk/{check-provider-registry-TTVN3V2O.mjs → check-provider-registry-V6C4LUYJ.mjs} +5 -5
- package/dist/sdk/{check-provider-registry-4SHN3GSH.mjs → check-provider-registry-WXEBJWXY.mjs} +5 -5
- package/dist/sdk/{chunk-EO4IJNM7.mjs → chunk-E7NRUDWL.mjs} +2 -2
- package/dist/sdk/{chunk-LDE33FGE.mjs → chunk-HFCOZPAS.mjs} +3 -3
- package/dist/sdk/{chunk-LDE33FGE.mjs.map → chunk-HFCOZPAS.mjs.map} +1 -1
- package/dist/sdk/{chunk-XDIBL7QB.mjs → chunk-KBTFMYZQ.mjs} +2 -2
- package/dist/sdk/{chunk-G5JBWW3O.mjs → chunk-KKGMGB4X.mjs} +160 -20
- package/dist/sdk/chunk-KKGMGB4X.mjs.map +1 -0
- package/dist/sdk/{chunk-GMHSXC5K.mjs → chunk-OQ3CML4F.mjs} +3 -3
- package/dist/sdk/{chunk-J236ZVYX.mjs → chunk-RV5SK4FZ.mjs} +3 -3
- package/dist/sdk/{chunk-S47KBQQK.mjs → chunk-T5USZCCM.mjs} +2 -2
- package/dist/sdk/{chunk-S47KBQQK.mjs.map → chunk-T5USZCCM.mjs.map} +1 -1
- package/dist/sdk/{chunk-GOJRNYTV.mjs → chunk-WSYVK6ML.mjs} +188 -22
- package/dist/sdk/chunk-WSYVK6ML.mjs.map +1 -0
- package/dist/sdk/{chunk-MYROK4LB.mjs → chunk-ZQR4AGS3.mjs} +160 -20
- package/dist/sdk/chunk-ZQR4AGS3.mjs.map +1 -0
- package/dist/sdk/{failure-condition-evaluator-N3VNLWZD.mjs → failure-condition-evaluator-5EAESM44.mjs} +3 -3
- package/dist/sdk/{failure-condition-evaluator-M6SIUQF4.mjs → failure-condition-evaluator-GPANOHP2.mjs} +3 -3
- package/dist/sdk/{github-frontend-ATORHHF6.mjs → github-frontend-BPRRUIGB.mjs} +3 -3
- package/dist/sdk/{github-frontend-MHXL2Q2V.mjs → github-frontend-P274ISBJ.mjs} +3 -3
- package/dist/sdk/{host-JROON6IT.mjs → host-753E6PKF.mjs} +2 -2
- package/dist/sdk/{host-OBXKDFT7.mjs → host-AIMRV5YL.mjs} +2 -2
- package/dist/sdk/{routing-QCDX43XD.mjs → routing-BXHP2E62.mjs} +4 -4
- package/dist/sdk/{routing-TGJD66Q5.mjs → routing-QHWSMAIH.mjs} +4 -4
- package/dist/sdk/{schedule-tool-D5TSTGP2.mjs → schedule-tool-MQHISNJ6.mjs} +5 -5
- package/dist/sdk/{schedule-tool-XCGJI2VB.mjs → schedule-tool-OCZGLKMJ.mjs} +5 -5
- package/dist/sdk/{schedule-tool-C5QN5OQU.mjs → schedule-tool-ZVOSSFN2.mjs} +5 -5
- package/dist/sdk/{schedule-tool-handler-DKHHPZAG.mjs → schedule-tool-handler-4NCS4ARE.mjs} +5 -5
- package/dist/sdk/{schedule-tool-handler-OKZ53WMC.mjs → schedule-tool-handler-BGOL2TOP.mjs} +5 -5
- package/dist/sdk/{schedule-tool-handler-ZUMPNAVY.mjs → schedule-tool-handler-TZYXM664.mjs} +5 -5
- package/dist/sdk/sdk.js +147 -7
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +4 -4
- package/dist/sdk/{trace-helpers-J5CJ4PUN.mjs → trace-helpers-CTHTK6V5.mjs} +2 -2
- package/dist/sdk/{trace-helpers-KFQJ7IAG.mjs → trace-helpers-UG6FOWVV.mjs} +2 -2
- package/dist/sdk/{workflow-check-provider-T6WFK4RB.mjs → workflow-check-provider-3M5LXLLX.mjs} +5 -5
- package/dist/sdk/{workflow-check-provider-WLUAJPAS.mjs → workflow-check-provider-QKHL6AFT.mjs} +5 -5
- package/dist/sdk/{workflow-check-provider-RBYA6ZGU.mjs → workflow-check-provider-UTNO6XN6.mjs} +5 -5
- package/dist/slack/socket-runner.d.ts +14 -0
- package/dist/slack/socket-runner.d.ts.map +1 -1
- package/dist/traces/{run-2026-03-06T06-08-10-897Z.ndjson → run-2026-03-06T13-08-34-152Z.ndjson} +84 -84
- package/dist/traces/{run-2026-03-06T06-08-55-016Z.ndjson → run-2026-03-06T13-09-10-593Z.ndjson} +1894 -1894
- package/dist/utils/oauth2-token-cache.d.ts +44 -0
- package/dist/utils/oauth2-token-cache.d.ts.map +1 -0
- package/package.json +2 -2
- package/dist/sdk/chunk-G5JBWW3O.mjs.map +0 -1
- package/dist/sdk/chunk-GOJRNYTV.mjs.map +0 -1
- package/dist/sdk/chunk-MYROK4LB.mjs.map +0 -1
- /package/dist/sdk/{check-provider-registry-4SHN3GSH.mjs.map → check-provider-registry-TGPICTHD.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-6P2KJ423.mjs.map → check-provider-registry-V6C4LUYJ.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-TTVN3V2O.mjs.map → check-provider-registry-WXEBJWXY.mjs.map} +0 -0
- /package/dist/sdk/{chunk-EO4IJNM7.mjs.map → chunk-E7NRUDWL.mjs.map} +0 -0
- /package/dist/sdk/{chunk-XDIBL7QB.mjs.map → chunk-KBTFMYZQ.mjs.map} +0 -0
- /package/dist/sdk/{chunk-GMHSXC5K.mjs.map → chunk-OQ3CML4F.mjs.map} +0 -0
- /package/dist/sdk/{chunk-J236ZVYX.mjs.map → chunk-RV5SK4FZ.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-M6SIUQF4.mjs.map → failure-condition-evaluator-5EAESM44.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-N3VNLWZD.mjs.map → failure-condition-evaluator-GPANOHP2.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-ATORHHF6.mjs.map → github-frontend-BPRRUIGB.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-MHXL2Q2V.mjs.map → github-frontend-P274ISBJ.mjs.map} +0 -0
- /package/dist/sdk/{host-JROON6IT.mjs.map → host-753E6PKF.mjs.map} +0 -0
- /package/dist/sdk/{host-OBXKDFT7.mjs.map → host-AIMRV5YL.mjs.map} +0 -0
- /package/dist/sdk/{routing-QCDX43XD.mjs.map → routing-BXHP2E62.mjs.map} +0 -0
- /package/dist/sdk/{routing-TGJD66Q5.mjs.map → routing-QHWSMAIH.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-C5QN5OQU.mjs.map → schedule-tool-MQHISNJ6.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-D5TSTGP2.mjs.map → schedule-tool-OCZGLKMJ.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-XCGJI2VB.mjs.map → schedule-tool-ZVOSSFN2.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-DKHHPZAG.mjs.map → schedule-tool-handler-4NCS4ARE.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-OKZ53WMC.mjs.map → schedule-tool-handler-BGOL2TOP.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-ZUMPNAVY.mjs.map → schedule-tool-handler-TZYXM664.mjs.map} +0 -0
- /package/dist/sdk/{trace-helpers-J5CJ4PUN.mjs.map → trace-helpers-CTHTK6V5.mjs.map} +0 -0
- /package/dist/sdk/{trace-helpers-KFQJ7IAG.mjs.map → trace-helpers-UG6FOWVV.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-RBYA6ZGU.mjs.map → workflow-check-provider-3M5LXLLX.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-T6WFK4RB.mjs.map → workflow-check-provider-QKHL6AFT.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-WLUAJPAS.mjs.map → workflow-check-provider-UTNO6XN6.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.
|
|
3
|
-
process.env.PROBE_VERSION = '0.6.0-
|
|
4
|
-
process.env.VISOR_COMMIT_SHA = '
|
|
5
|
-
process.env.VISOR_COMMIT_SHORT = '
|
|
2
|
+
process.env.VISOR_VERSION = '0.1.166';
|
|
3
|
+
process.env.PROBE_VERSION = '0.6.0-rc280';
|
|
4
|
+
process.env.VISOR_COMMIT_SHA = 'eff5ed2df07d89e22e1c88d7d96b97572b0fd908';
|
|
5
|
+
process.env.VISOR_COMMIT_SHORT = 'eff5ed2df';
|
|
6
6
|
/******/ (() => { // webpackBootstrap
|
|
7
7
|
/******/ var __webpack_modules__ = ({
|
|
8
8
|
|
|
@@ -178585,10 +178585,12 @@ const file_exclusion_1 = __nccwpck_require__(69342);
|
|
|
178585
178585
|
class PRAnalyzer {
|
|
178586
178586
|
octokit;
|
|
178587
178587
|
maxRetries;
|
|
178588
|
+
baseDelay;
|
|
178588
178589
|
fileExclusionHelper;
|
|
178589
|
-
constructor(octokit, maxRetries = 3, workingDirectory = path.resolve(process.cwd())) {
|
|
178590
|
+
constructor(octokit, maxRetries = 3, workingDirectory = path.resolve(process.cwd()), baseDelay = 1000) {
|
|
178590
178591
|
this.octokit = octokit;
|
|
178591
178592
|
this.maxRetries = maxRetries;
|
|
178593
|
+
this.baseDelay = baseDelay;
|
|
178592
178594
|
this.fileExclusionHelper = new file_exclusion_1.FileExclusionHelper(workingDirectory);
|
|
178593
178595
|
}
|
|
178594
178596
|
/**
|
|
@@ -178780,7 +178782,7 @@ class PRAnalyzer {
|
|
|
178780
178782
|
}
|
|
178781
178783
|
// Check if this is a retryable error
|
|
178782
178784
|
if (this.isRetryableError(error)) {
|
|
178783
|
-
const delay = Math.min(
|
|
178785
|
+
const delay = Math.min(this.baseDelay * Math.pow(2, attempt), this.baseDelay * 5); // Exponential backoff
|
|
178784
178786
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
178785
178787
|
}
|
|
178786
178788
|
else {
|
|
@@ -185511,6 +185513,7 @@ const liquid_extensions_1 = __nccwpck_require__(33042);
|
|
|
185511
185513
|
const env_resolver_1 = __nccwpck_require__(58749);
|
|
185512
185514
|
const sandbox_1 = __nccwpck_require__(12630);
|
|
185513
185515
|
const template_context_1 = __nccwpck_require__(1581);
|
|
185516
|
+
const oauth2_token_cache_1 = __nccwpck_require__(34713);
|
|
185514
185517
|
const logger_1 = __nccwpck_require__(86999);
|
|
185515
185518
|
const fs = __importStar(__nccwpck_require__(79896));
|
|
185516
185519
|
const path = __importStar(__nccwpck_require__(16928));
|
|
@@ -185542,13 +185545,15 @@ class HttpClientProvider extends check_provider_interface_1.CheckProvider {
|
|
|
185542
185545
|
if (cfg.type !== 'http_client') {
|
|
185543
185546
|
return false;
|
|
185544
185547
|
}
|
|
185545
|
-
// Must have
|
|
185546
|
-
|
|
185548
|
+
// Must have either `url` or `base_url` specified
|
|
185549
|
+
const hasUrl = typeof cfg.url === 'string' && cfg.url;
|
|
185550
|
+
const hasBaseUrl = typeof cfg.base_url === 'string' && cfg.base_url;
|
|
185551
|
+
if (!hasUrl && !hasBaseUrl) {
|
|
185547
185552
|
return false;
|
|
185548
185553
|
}
|
|
185549
|
-
// Validate URL format
|
|
185554
|
+
// Validate URL format (check whichever is provided)
|
|
185550
185555
|
try {
|
|
185551
|
-
new URL(cfg.url);
|
|
185556
|
+
new URL((hasUrl ? cfg.url : cfg.base_url));
|
|
185552
185557
|
return true;
|
|
185553
185558
|
}
|
|
185554
185559
|
catch {
|
|
@@ -185556,13 +185561,34 @@ class HttpClientProvider extends check_provider_interface_1.CheckProvider {
|
|
|
185556
185561
|
}
|
|
185557
185562
|
}
|
|
185558
185563
|
async execute(prInfo, config, dependencyResults, context) {
|
|
185559
|
-
const
|
|
185564
|
+
const baseUrl = config.base_url;
|
|
185565
|
+
const rawPath = config.path;
|
|
185566
|
+
const pathParams = config.params || {};
|
|
185567
|
+
const queryParams = config.query || {};
|
|
185568
|
+
const authConfig = config.auth;
|
|
185569
|
+
// Build URL: either direct `url` or `base_url` + `path` with param substitution
|
|
185570
|
+
let url;
|
|
185571
|
+
if (baseUrl && rawPath) {
|
|
185572
|
+
// Substitute {param} placeholders in path
|
|
185573
|
+
let resolvedPath = rawPath;
|
|
185574
|
+
for (const [key, value] of Object.entries(pathParams)) {
|
|
185575
|
+
resolvedPath = resolvedPath.replace(`{${key}}`, encodeURIComponent(value));
|
|
185576
|
+
}
|
|
185577
|
+
url = `${baseUrl.replace(/\/+$/, '')}/${resolvedPath.replace(/^\/+/, '')}`;
|
|
185578
|
+
// Append query parameters
|
|
185579
|
+
if (Object.keys(queryParams).length > 0) {
|
|
185580
|
+
const qs = new URLSearchParams(queryParams).toString();
|
|
185581
|
+
url += `${url.includes('?') ? '&' : '?'}${qs}`;
|
|
185582
|
+
}
|
|
185583
|
+
}
|
|
185584
|
+
else {
|
|
185585
|
+
url = config.url;
|
|
185586
|
+
}
|
|
185560
185587
|
const method = config.method || 'GET';
|
|
185561
185588
|
const headers = config.headers || {};
|
|
185562
185589
|
const timeout = config.timeout || 30000;
|
|
185563
185590
|
const transform = config.transform;
|
|
185564
185591
|
const transformJs = config.transform_js;
|
|
185565
|
-
const bodyTemplate = config.body;
|
|
185566
185592
|
const outputFileTemplate = config.output_file;
|
|
185567
185593
|
const skipIfExists = config.skip_if_exists !== false; // Default true for caching
|
|
185568
185594
|
// Track resolved URL for error messages
|
|
@@ -185583,9 +185609,14 @@ class HttpClientProvider extends check_provider_interface_1.CheckProvider {
|
|
|
185583
185609
|
renderedUrl = await this.liquid.parseAndRender(renderedUrl, templateContext);
|
|
185584
185610
|
resolvedUrlForErrors = renderedUrl; // Update after Liquid rendering
|
|
185585
185611
|
}
|
|
185586
|
-
// Prepare request body
|
|
185612
|
+
// Prepare request body — supports both Liquid template strings and JSON objects
|
|
185587
185613
|
let requestBody;
|
|
185588
|
-
|
|
185614
|
+
const rawBody = config.body;
|
|
185615
|
+
const bodyTemplate = typeof rawBody === 'string' ? rawBody : undefined;
|
|
185616
|
+
if (rawBody && typeof rawBody === 'object') {
|
|
185617
|
+
requestBody = JSON.stringify(rawBody);
|
|
185618
|
+
}
|
|
185619
|
+
else if (bodyTemplate) {
|
|
185589
185620
|
// First resolve shell-style environment variables
|
|
185590
185621
|
let resolvedBody = String(env_resolver_1.EnvironmentResolver.resolveValue(bodyTemplate));
|
|
185591
185622
|
// Then render Liquid templates if present
|
|
@@ -185611,6 +185642,12 @@ class HttpClientProvider extends check_provider_interface_1.CheckProvider {
|
|
|
185611
185642
|
logger_1.logger.verbose(`[http_client] ${key}: ${maskedValue}`);
|
|
185612
185643
|
}
|
|
185613
185644
|
}
|
|
185645
|
+
// Inject OAuth2 Bearer token if auth config is provided
|
|
185646
|
+
if (authConfig?.type === 'oauth2_client_credentials') {
|
|
185647
|
+
const tokenCache = oauth2_token_cache_1.OAuth2TokenCache.getInstance();
|
|
185648
|
+
const token = await tokenCache.getToken(authConfig);
|
|
185649
|
+
resolvedHeaders['Authorization'] = `Bearer ${token}`;
|
|
185650
|
+
}
|
|
185614
185651
|
// Resolve output_file path if specified
|
|
185615
185652
|
let resolvedOutputFile;
|
|
185616
185653
|
if (outputFileTemplate) {
|
|
@@ -185908,6 +185945,11 @@ class HttpClientProvider extends check_provider_interface_1.CheckProvider {
|
|
|
185908
185945
|
return [
|
|
185909
185946
|
'type',
|
|
185910
185947
|
'url',
|
|
185948
|
+
'base_url',
|
|
185949
|
+
'path',
|
|
185950
|
+
'params',
|
|
185951
|
+
'query',
|
|
185952
|
+
'auth',
|
|
185911
185953
|
'method',
|
|
185912
185954
|
'headers',
|
|
185913
185955
|
'body',
|
|
@@ -198589,6 +198631,9 @@ class SlackSocketRunner {
|
|
|
198589
198631
|
genericScheduler;
|
|
198590
198632
|
messageTriggerEvaluator;
|
|
198591
198633
|
activeThreads = new Set();
|
|
198634
|
+
heartbeatTimer;
|
|
198635
|
+
lastPong = 0;
|
|
198636
|
+
closing = false; // prevent duplicate reconnects
|
|
198592
198637
|
constructor(engine, cfg, opts) {
|
|
198593
198638
|
const app = opts.appToken || process.env.SLACK_APP_TOKEN || '';
|
|
198594
198639
|
if (!app)
|
|
@@ -198779,21 +198824,93 @@ class SlackSocketRunner {
|
|
|
198779
198824
|
return json.url;
|
|
198780
198825
|
}
|
|
198781
198826
|
async connect(url) {
|
|
198782
|
-
|
|
198783
|
-
this.
|
|
198827
|
+
// Close previous WebSocket to prevent ghost event handlers
|
|
198828
|
+
this.closeWebSocket();
|
|
198829
|
+
const ws = new ws_1.default(url);
|
|
198830
|
+
this.ws = ws;
|
|
198831
|
+
this.closing = false;
|
|
198832
|
+
ws.on('open', () => {
|
|
198784
198833
|
this.retryCount = 0; // Reset on successful connection
|
|
198834
|
+
this.lastPong = Date.now();
|
|
198785
198835
|
logger_1.logger.info('[SlackSocket] WebSocket connected');
|
|
198836
|
+
this.startHeartbeat();
|
|
198786
198837
|
});
|
|
198787
|
-
|
|
198838
|
+
ws.on('close', (code, reason) => {
|
|
198788
198839
|
logger_1.logger.warn(`[SlackSocket] WebSocket closed: ${code} ${reason}`);
|
|
198789
|
-
|
|
198840
|
+
this.stopHeartbeat();
|
|
198841
|
+
// Only reconnect if this is still the active WebSocket
|
|
198842
|
+
if (this.ws === ws && !this.closing) {
|
|
198843
|
+
this.closing = true;
|
|
198844
|
+
setTimeout(() => this.restart(), 1000);
|
|
198845
|
+
}
|
|
198790
198846
|
});
|
|
198791
|
-
|
|
198847
|
+
ws.on('error', err => {
|
|
198792
198848
|
logger_1.logger.error(`[SlackSocket] WebSocket error: ${err}`);
|
|
198793
198849
|
});
|
|
198794
|
-
|
|
198850
|
+
ws.on('pong', () => {
|
|
198851
|
+
this.lastPong = Date.now();
|
|
198852
|
+
});
|
|
198853
|
+
ws.on('message', data => this.handleMessage(data.toString()).catch(() => { }));
|
|
198854
|
+
}
|
|
198855
|
+
/**
|
|
198856
|
+
* Close the current WebSocket connection and stop heartbeat.
|
|
198857
|
+
* Safe to call multiple times.
|
|
198858
|
+
*/
|
|
198859
|
+
closeWebSocket() {
|
|
198860
|
+
this.stopHeartbeat();
|
|
198861
|
+
if (this.ws) {
|
|
198862
|
+
const old = this.ws;
|
|
198863
|
+
this.ws = undefined;
|
|
198864
|
+
try {
|
|
198865
|
+
// Remove listeners to prevent ghost close/message handlers
|
|
198866
|
+
old.removeAllListeners();
|
|
198867
|
+
old.close();
|
|
198868
|
+
}
|
|
198869
|
+
catch {
|
|
198870
|
+
// best effort
|
|
198871
|
+
}
|
|
198872
|
+
}
|
|
198873
|
+
}
|
|
198874
|
+
/**
|
|
198875
|
+
* Start periodic WebSocket ping to detect dead connections.
|
|
198876
|
+
* If no pong is received within 60s, force a reconnect.
|
|
198877
|
+
*/
|
|
198878
|
+
startHeartbeat() {
|
|
198879
|
+
this.stopHeartbeat();
|
|
198880
|
+
const PING_INTERVAL_MS = 30_000; // ping every 30s
|
|
198881
|
+
const PONG_TIMEOUT_MS = 60_000; // dead if no pong for 60s
|
|
198882
|
+
this.heartbeatTimer = setInterval(() => {
|
|
198883
|
+
if (!this.ws || this.ws.readyState !== ws_1.default.OPEN)
|
|
198884
|
+
return;
|
|
198885
|
+
// Check if last pong is stale
|
|
198886
|
+
const sincePong = Date.now() - this.lastPong;
|
|
198887
|
+
if (this.lastPong > 0 && sincePong > PONG_TIMEOUT_MS) {
|
|
198888
|
+
logger_1.logger.warn(`[SlackSocket] No pong received for ${Math.round(sincePong / 1000)}s, forcing reconnect`);
|
|
198889
|
+
this.closeWebSocket();
|
|
198890
|
+
this.closing = true;
|
|
198891
|
+
this.restart();
|
|
198892
|
+
return;
|
|
198893
|
+
}
|
|
198894
|
+
try {
|
|
198895
|
+
this.ws.ping();
|
|
198896
|
+
}
|
|
198897
|
+
catch {
|
|
198898
|
+
// ping failed — connection is likely dead
|
|
198899
|
+
logger_1.logger.warn('[SlackSocket] Ping failed, forcing reconnect');
|
|
198900
|
+
this.closeWebSocket();
|
|
198901
|
+
this.closing = true;
|
|
198902
|
+
this.restart();
|
|
198903
|
+
}
|
|
198904
|
+
}, PING_INTERVAL_MS);
|
|
198905
|
+
}
|
|
198906
|
+
stopHeartbeat() {
|
|
198907
|
+
if (this.heartbeatTimer) {
|
|
198908
|
+
clearInterval(this.heartbeatTimer);
|
|
198909
|
+
this.heartbeatTimer = undefined;
|
|
198910
|
+
}
|
|
198795
198911
|
}
|
|
198796
198912
|
async restart() {
|
|
198913
|
+
this.closing = false;
|
|
198797
198914
|
try {
|
|
198798
198915
|
const url = await this.openConnection();
|
|
198799
198916
|
await this.connect(url);
|
|
@@ -198803,7 +198920,7 @@ class SlackSocketRunner {
|
|
|
198803
198920
|
// Exponential backoff: 2s, 4s, 8s, 16s, 32s, capped at 60s
|
|
198804
198921
|
const delay = Math.min(2000 * Math.pow(2, this.retryCount - 1), 60000);
|
|
198805
198922
|
logger_1.logger.error(`[SlackSocket] Restart failed (attempt ${this.retryCount}), retrying in ${Math.round(delay / 1000)}s: ${e instanceof Error ? e.message : e}`);
|
|
198806
|
-
setTimeout(() => this.restart()
|
|
198923
|
+
setTimeout(() => this.restart(), delay);
|
|
198807
198924
|
}
|
|
198808
198925
|
}
|
|
198809
198926
|
send(obj) {
|
|
@@ -198881,6 +198998,16 @@ class SlackSocketRunner {
|
|
|
198881
198998
|
return;
|
|
198882
198999
|
if (env.envelope_id)
|
|
198883
199000
|
this.send({ envelope_id: env.envelope_id }); // ack ASAP
|
|
199001
|
+
// Handle Slack disconnect events — proactively reconnect before the connection dies
|
|
199002
|
+
if (env.type === 'disconnect') {
|
|
199003
|
+
const reason = env.reason || 'unknown';
|
|
199004
|
+
logger_1.logger.info(`[SlackSocket] Received disconnect event (reason: ${reason}), reconnecting`);
|
|
199005
|
+
// Slack will close the connection shortly; proactively reconnect now
|
|
199006
|
+
this.closeWebSocket();
|
|
199007
|
+
this.closing = true;
|
|
199008
|
+
this.restart();
|
|
199009
|
+
return;
|
|
199010
|
+
}
|
|
198884
199011
|
if (env.type !== 'events_api' || !env.payload) {
|
|
198885
199012
|
if (process.env.VISOR_DEBUG === 'true') {
|
|
198886
199013
|
logger_1.logger.debug(`[SlackSocket] Dropping non-events payload: type=${String(env.type || '-')}`);
|
|
@@ -199584,17 +199711,10 @@ class SlackSocketRunner {
|
|
|
199584
199711
|
logger_1.logger.warn(`[SlackSocket] Error stopping generic scheduler: ${e instanceof Error ? e.message : e}`);
|
|
199585
199712
|
}
|
|
199586
199713
|
}
|
|
199587
|
-
// Close WebSocket connection
|
|
199588
|
-
|
|
199589
|
-
|
|
199590
|
-
|
|
199591
|
-
this.ws = undefined;
|
|
199592
|
-
logger_1.logger.info('[SlackSocket] WebSocket closed');
|
|
199593
|
-
}
|
|
199594
|
-
catch {
|
|
199595
|
-
// Best effort
|
|
199596
|
-
}
|
|
199597
|
-
}
|
|
199714
|
+
// Close WebSocket connection and stop heartbeat
|
|
199715
|
+
this.closing = true; // prevent reconnect on close
|
|
199716
|
+
this.closeWebSocket();
|
|
199717
|
+
logger_1.logger.info('[SlackSocket] WebSocket closed');
|
|
199598
199718
|
}
|
|
199599
199719
|
/**
|
|
199600
199720
|
* Get the scheduler instance
|
|
@@ -221188,6 +221308,130 @@ function emitMermaidFromMarkdown(checkName, markdown, origin) {
|
|
|
221188
221308
|
}
|
|
221189
221309
|
|
|
221190
221310
|
|
|
221311
|
+
/***/ }),
|
|
221312
|
+
|
|
221313
|
+
/***/ 34713:
|
|
221314
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
221315
|
+
|
|
221316
|
+
"use strict";
|
|
221317
|
+
|
|
221318
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
221319
|
+
exports.OAuth2TokenCache = void 0;
|
|
221320
|
+
const logger_1 = __nccwpck_require__(86999);
|
|
221321
|
+
const env_resolver_1 = __nccwpck_require__(58749);
|
|
221322
|
+
/**
|
|
221323
|
+
* Singleton cache for OAuth2 tokens.
|
|
221324
|
+
*
|
|
221325
|
+
* - Keyed by hash(token_url + client_id) to support multiple providers
|
|
221326
|
+
* - Lazy refresh: only fetches when expired or near-expiry
|
|
221327
|
+
* - Deduplicates concurrent requests: if two calls hit with an expired token,
|
|
221328
|
+
* both await the same fetch promise
|
|
221329
|
+
*/
|
|
221330
|
+
class OAuth2TokenCache {
|
|
221331
|
+
static instance;
|
|
221332
|
+
cache = new Map();
|
|
221333
|
+
static getInstance() {
|
|
221334
|
+
if (!OAuth2TokenCache.instance) {
|
|
221335
|
+
OAuth2TokenCache.instance = new OAuth2TokenCache();
|
|
221336
|
+
}
|
|
221337
|
+
return OAuth2TokenCache.instance;
|
|
221338
|
+
}
|
|
221339
|
+
/** Visible for testing */
|
|
221340
|
+
static resetInstance() {
|
|
221341
|
+
OAuth2TokenCache.instance = undefined;
|
|
221342
|
+
}
|
|
221343
|
+
/**
|
|
221344
|
+
* Get a valid Bearer token for the given config.
|
|
221345
|
+
* Returns a cached token if still valid, otherwise fetches a new one.
|
|
221346
|
+
*/
|
|
221347
|
+
async getToken(config) {
|
|
221348
|
+
const clientId = String(env_resolver_1.EnvironmentResolver.resolveValue(config.client_id));
|
|
221349
|
+
const clientSecret = String(env_resolver_1.EnvironmentResolver.resolveValue(config.client_secret));
|
|
221350
|
+
const tokenUrl = String(env_resolver_1.EnvironmentResolver.resolveValue(config.token_url));
|
|
221351
|
+
const bufferMs = (config.token_ttl_buffer ?? 300) * 1000;
|
|
221352
|
+
const cacheKey = `${tokenUrl}|${clientId}`;
|
|
221353
|
+
const cached = this.cache.get(cacheKey);
|
|
221354
|
+
// Return cached token if still valid (with buffer)
|
|
221355
|
+
if (cached && cached.expires_at - bufferMs > Date.now()) {
|
|
221356
|
+
logger_1.logger.verbose('[oauth2] Using cached token');
|
|
221357
|
+
return cached.access_token;
|
|
221358
|
+
}
|
|
221359
|
+
// If another request is already refreshing, await it
|
|
221360
|
+
if (cached?.refreshPromise) {
|
|
221361
|
+
logger_1.logger.verbose('[oauth2] Awaiting in-flight token refresh');
|
|
221362
|
+
return cached.refreshPromise;
|
|
221363
|
+
}
|
|
221364
|
+
// Fetch a new token
|
|
221365
|
+
const refreshPromise = this.fetchToken(tokenUrl, clientId, clientSecret, config.scopes);
|
|
221366
|
+
// Store the promise so concurrent callers share it
|
|
221367
|
+
if (cached) {
|
|
221368
|
+
cached.refreshPromise = refreshPromise;
|
|
221369
|
+
}
|
|
221370
|
+
else {
|
|
221371
|
+
this.cache.set(cacheKey, {
|
|
221372
|
+
access_token: '',
|
|
221373
|
+
expires_at: 0,
|
|
221374
|
+
refreshPromise,
|
|
221375
|
+
});
|
|
221376
|
+
}
|
|
221377
|
+
try {
|
|
221378
|
+
const token = await refreshPromise;
|
|
221379
|
+
return token;
|
|
221380
|
+
}
|
|
221381
|
+
finally {
|
|
221382
|
+
// Clear the in-flight promise regardless of outcome
|
|
221383
|
+
const entry = this.cache.get(cacheKey);
|
|
221384
|
+
if (entry) {
|
|
221385
|
+
entry.refreshPromise = undefined;
|
|
221386
|
+
}
|
|
221387
|
+
}
|
|
221388
|
+
}
|
|
221389
|
+
async fetchToken(tokenUrl, clientId, clientSecret, scopes) {
|
|
221390
|
+
logger_1.logger.verbose(`[oauth2] Fetching token from ${tokenUrl}`);
|
|
221391
|
+
const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
|
|
221392
|
+
const bodyParams = new URLSearchParams({ grant_type: 'client_credentials' });
|
|
221393
|
+
if (scopes?.length) {
|
|
221394
|
+
bodyParams.set('scope', scopes.join(' '));
|
|
221395
|
+
}
|
|
221396
|
+
const response = await fetch(tokenUrl, {
|
|
221397
|
+
method: 'POST',
|
|
221398
|
+
headers: {
|
|
221399
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
221400
|
+
Authorization: `Basic ${credentials}`,
|
|
221401
|
+
},
|
|
221402
|
+
body: bodyParams.toString(),
|
|
221403
|
+
});
|
|
221404
|
+
if (!response.ok) {
|
|
221405
|
+
let errorDetail = '';
|
|
221406
|
+
try {
|
|
221407
|
+
errorDetail = await response.text();
|
|
221408
|
+
}
|
|
221409
|
+
catch { }
|
|
221410
|
+
throw new Error(`OAuth2 token request failed: HTTP ${response.status} ${response.statusText}${errorDetail ? ` - ${errorDetail.substring(0, 200)}` : ''}`);
|
|
221411
|
+
}
|
|
221412
|
+
const data = (await response.json());
|
|
221413
|
+
if (!data.access_token) {
|
|
221414
|
+
throw new Error('OAuth2 token response missing access_token');
|
|
221415
|
+
}
|
|
221416
|
+
// Default to 1 hour if expires_in not provided
|
|
221417
|
+
const expiresIn = data.expires_in ?? 3600;
|
|
221418
|
+
const expiresAt = Date.now() + expiresIn * 1000;
|
|
221419
|
+
const cacheKey = `${tokenUrl}|${clientId}`;
|
|
221420
|
+
this.cache.set(cacheKey, {
|
|
221421
|
+
access_token: data.access_token,
|
|
221422
|
+
expires_at: expiresAt,
|
|
221423
|
+
});
|
|
221424
|
+
logger_1.logger.verbose(`[oauth2] Token acquired, expires in ${expiresIn}s`);
|
|
221425
|
+
return data.access_token;
|
|
221426
|
+
}
|
|
221427
|
+
/** Clear all cached tokens (for testing or credential rotation) */
|
|
221428
|
+
clear() {
|
|
221429
|
+
this.cache.clear();
|
|
221430
|
+
}
|
|
221431
|
+
}
|
|
221432
|
+
exports.OAuth2TokenCache = OAuth2TokenCache;
|
|
221433
|
+
|
|
221434
|
+
|
|
221191
221435
|
/***/ }),
|
|
221192
221436
|
|
|
221193
221437
|
/***/ 12630:
|
|
@@ -248108,9 +248352,7 @@ async function acquireFileLock(lockPath, version2) {
|
|
|
248108
248352
|
};
|
|
248109
248353
|
try {
|
|
248110
248354
|
await import_fs_extra2.default.writeFile(lockPath, JSON.stringify(lockData), { flag: "wx" });
|
|
248111
|
-
|
|
248112
|
-
console.log(`Acquired file lock: ${lockPath}`);
|
|
248113
|
-
}
|
|
248355
|
+
console.log(`Acquired file lock: ${lockPath}`);
|
|
248114
248356
|
return true;
|
|
248115
248357
|
} catch (error2) {
|
|
248116
248358
|
if (error2.code === "EEXIST") {
|
|
@@ -248118,15 +248360,11 @@ async function acquireFileLock(lockPath, version2) {
|
|
|
248118
248360
|
const existingLock = JSON.parse(await import_fs_extra2.default.readFile(lockPath, "utf-8"));
|
|
248119
248361
|
const lockAge = Date.now() - existingLock.timestamp;
|
|
248120
248362
|
if (lockAge > LOCK_TIMEOUT_MS) {
|
|
248121
|
-
|
|
248122
|
-
console.log(`Removing stale lock file (age: ${Math.round(lockAge / 1e3)}s, pid: ${existingLock.pid})`);
|
|
248123
|
-
}
|
|
248363
|
+
console.log(`Removing stale lock file (age: ${Math.round(lockAge / 1e3)}s, pid: ${existingLock.pid})`);
|
|
248124
248364
|
await import_fs_extra2.default.remove(lockPath);
|
|
248125
248365
|
return false;
|
|
248126
248366
|
}
|
|
248127
|
-
|
|
248128
|
-
console.log(`Download in progress by process ${existingLock.pid}, waiting...`);
|
|
248129
|
-
}
|
|
248367
|
+
console.log(`Download in progress by process ${existingLock.pid}, waiting...`);
|
|
248130
248368
|
return false;
|
|
248131
248369
|
} catch (readError) {
|
|
248132
248370
|
if (process.env.DEBUG === "1" || process.env.VERBOSE === "1") {
|
|
@@ -248167,36 +248405,36 @@ async function releaseFileLock(lockPath) {
|
|
|
248167
248405
|
}
|
|
248168
248406
|
async function waitForFileLock(lockPath, binaryPath) {
|
|
248169
248407
|
const startTime = Date.now();
|
|
248408
|
+
let lastStatusTime = startTime;
|
|
248409
|
+
console.log(`Waiting for file lock to clear: ${lockPath}`);
|
|
248170
248410
|
while (Date.now() - startTime < MAX_LOCK_WAIT_MS) {
|
|
248171
248411
|
if (await import_fs_extra2.default.pathExists(binaryPath)) {
|
|
248172
|
-
|
|
248173
|
-
|
|
248174
|
-
}
|
|
248412
|
+
const waitedSeconds = Math.round((Date.now() - startTime) / 1e3);
|
|
248413
|
+
console.log(`Binary now available at ${binaryPath}, download completed by another process (waited ${waitedSeconds}s)`);
|
|
248175
248414
|
return true;
|
|
248176
248415
|
}
|
|
248177
248416
|
const lockExists = await import_fs_extra2.default.pathExists(lockPath);
|
|
248178
248417
|
if (!lockExists) {
|
|
248179
|
-
|
|
248180
|
-
console.log(`Lock file removed but binary not found - download may have failed`);
|
|
248181
|
-
}
|
|
248418
|
+
console.log(`Lock file removed but binary not found - download may have failed`);
|
|
248182
248419
|
return false;
|
|
248183
248420
|
}
|
|
248184
248421
|
try {
|
|
248185
248422
|
const lockData = JSON.parse(await import_fs_extra2.default.readFile(lockPath, "utf-8"));
|
|
248186
248423
|
const lockAge = Date.now() - lockData.timestamp;
|
|
248187
248424
|
if (lockAge > LOCK_TIMEOUT_MS) {
|
|
248188
|
-
|
|
248189
|
-
console.log(`Lock expired (age: ${Math.round(lockAge / 1e3)}s), will retry download`);
|
|
248190
|
-
}
|
|
248425
|
+
console.log(`Lock expired (age: ${Math.round(lockAge / 1e3)}s), will retry download`);
|
|
248191
248426
|
return false;
|
|
248192
248427
|
}
|
|
248193
248428
|
} catch {
|
|
248194
248429
|
}
|
|
248430
|
+
if (Date.now() - lastStatusTime >= 15e3) {
|
|
248431
|
+
const elapsedSeconds = Math.round((Date.now() - startTime) / 1e3);
|
|
248432
|
+
console.log(`Still waiting for file lock (${elapsedSeconds}s/${MAX_LOCK_WAIT_MS / 1e3}s max)`);
|
|
248433
|
+
lastStatusTime = Date.now();
|
|
248434
|
+
}
|
|
248195
248435
|
await new Promise((resolve8) => setTimeout(resolve8, LOCK_POLL_INTERVAL_MS));
|
|
248196
248436
|
}
|
|
248197
|
-
|
|
248198
|
-
console.log(`Timeout waiting for file lock`);
|
|
248199
|
-
}
|
|
248437
|
+
console.log(`Timeout waiting for file lock after ${MAX_LOCK_WAIT_MS / 1e3}s`);
|
|
248200
248438
|
return false;
|
|
248201
248439
|
}
|
|
248202
248440
|
async function withDownloadLock(version2, downloadFn) {
|
|
@@ -248210,9 +248448,7 @@ async function withDownloadLock(version2, downloadFn) {
|
|
|
248210
248448
|
}
|
|
248211
248449
|
downloadLocks.delete(lockKey);
|
|
248212
248450
|
} else {
|
|
248213
|
-
|
|
248214
|
-
console.log(`Download already in progress in this process for version ${lockKey}, waiting...`);
|
|
248215
|
-
}
|
|
248451
|
+
console.log(`Download already in progress in this process for version ${lockKey}, waiting...`);
|
|
248216
248452
|
try {
|
|
248217
248453
|
return await lock.promise;
|
|
248218
248454
|
} catch (error2) {
|
|
@@ -248222,10 +248458,16 @@ async function withDownloadLock(version2, downloadFn) {
|
|
|
248222
248458
|
}
|
|
248223
248459
|
}
|
|
248224
248460
|
}
|
|
248461
|
+
let timeoutId = null;
|
|
248225
248462
|
const downloadPromise = Promise.race([
|
|
248226
248463
|
downloadFn(),
|
|
248227
248464
|
new Promise(
|
|
248228
|
-
(_, reject2) =>
|
|
248465
|
+
(_, reject2) => {
|
|
248466
|
+
timeoutId = setTimeout(() => reject2(new Error(`Download timeout after ${LOCK_TIMEOUT_MS / 1e3}s`)), LOCK_TIMEOUT_MS);
|
|
248467
|
+
if (timeoutId.unref) {
|
|
248468
|
+
timeoutId.unref();
|
|
248469
|
+
}
|
|
248470
|
+
}
|
|
248229
248471
|
)
|
|
248230
248472
|
]);
|
|
248231
248473
|
downloadLocks.set(lockKey, {
|
|
@@ -248236,6 +248478,9 @@ async function withDownloadLock(version2, downloadFn) {
|
|
|
248236
248478
|
const result = await downloadPromise;
|
|
248237
248479
|
return result;
|
|
248238
248480
|
} finally {
|
|
248481
|
+
if (timeoutId) {
|
|
248482
|
+
clearTimeout(timeoutId);
|
|
248483
|
+
}
|
|
248239
248484
|
downloadLocks.delete(lockKey);
|
|
248240
248485
|
}
|
|
248241
248486
|
}
|
|
@@ -283766,14 +284011,14 @@ function resolveTargetPath(target, cwd) {
|
|
|
283766
284011
|
}
|
|
283767
284012
|
return filePart + suffix;
|
|
283768
284013
|
}
|
|
283769
|
-
var import_path5, searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, listFilesSchema, searchFilesSchema, readImageSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription;
|
|
284014
|
+
var import_path5, searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, listFilesSchema, searchFilesSchema, readImageSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchDescription, searchDelegateDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription;
|
|
283770
284015
|
var init_common2 = __esm({
|
|
283771
284016
|
"src/tools/common.js"() {
|
|
283772
284017
|
"use strict";
|
|
283773
284018
|
init_zod();
|
|
283774
284019
|
import_path5 = __nccwpck_require__(16928);
|
|
283775
284020
|
searchSchema = external_exports.object({
|
|
283776
|
-
query: external_exports.string().describe("Search query
|
|
284021
|
+
query: external_exports.string().describe("Search query \u2014 natural language questions or Elasticsearch-style keywords both work. For keywords: use quotes for exact phrases, AND/OR for boolean logic, - for negation. Probe handles stemming and camelCase/snake_case splitting automatically, so do NOT try case or style variations of the same keyword."),
|
|
283777
284022
|
path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
|
|
283778
284023
|
exact: external_exports.boolean().optional().default(false).describe('Default (false) enables stemming and keyword splitting for exploratory search - "getUserData" matches "get", "user", "data", etc. Set true for precise symbol lookup where "getUserData" matches only "getUserData". Use true when you know the exact symbol name.'),
|
|
283779
284024
|
maxTokens: external_exports.number().nullable().optional().describe("Maximum tokens to return. Default is 20000. Set to null for unlimited results."),
|
|
@@ -283781,7 +284026,7 @@ var init_common2 = __esm({
|
|
|
283781
284026
|
nextPage: external_exports.boolean().optional().default(false).describe("Set to true when requesting the next page of results. Requires passing the same session ID from the previous search output.")
|
|
283782
284027
|
});
|
|
283783
284028
|
searchAllSchema = external_exports.object({
|
|
283784
|
-
query: external_exports.string().describe("Search query
|
|
284029
|
+
query: external_exports.string().describe("Search query \u2014 natural language questions or Elasticsearch-style keywords both work. For keywords: use quotes for exact phrases, AND/OR for boolean logic, - for negation. Probe handles stemming and camelCase/snake_case splitting automatically, so do NOT try case or style variations of the same keyword."),
|
|
283785
284030
|
path: external_exports.string().optional().default(".").describe("Path to search in."),
|
|
283786
284031
|
exact: external_exports.boolean().optional().default(false).describe("Use exact matching instead of stemming."),
|
|
283787
284032
|
maxTokensPerPage: external_exports.number().optional().default(2e4).describe("Tokens per page when paginating. Default 20000."),
|
|
@@ -283888,7 +284133,8 @@ var init_common2 = __esm({
|
|
|
283888
284133
|
};
|
|
283889
284134
|
}
|
|
283890
284135
|
};
|
|
283891
|
-
searchDescription =
|
|
284136
|
+
searchDescription = 'Search code in the repository. Free-form questions are accepted, but Elasticsearch-style keyword queries work best. Use this tool first for any code-related questions. NOTE: By default, search handles stemming, case-insensitive matching, and camelCase/snake_case splitting automatically \u2014 do NOT manually try keyword variations like "getAllUsers" then "get_all_users" then "GetAllUsers". One search covers all variations.';
|
|
284137
|
+
searchDelegateDescription = 'Search code in the repository by asking a question. Accepts natural language questions (e.g., "How does authentication work?", "Where is the user validation logic?"). A specialized subagent breaks down your question into targeted keyword searches and returns extracted code blocks. Do NOT formulate keyword queries yourself \u2014 just ask the question naturally.';
|
|
283892
284138
|
queryDescription = "Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.";
|
|
283893
284139
|
extractDescription = "Extract code blocks from files based on file paths and optional line numbers. Use this tool to see complete context after finding relevant files. Line numbers from output can be used with edit start_line/end_line for precise editing.";
|
|
283894
284140
|
delegateDescription = "Automatically delegate big distinct tasks to specialized probe subagents within the agentic loop. Used by AI agents to break down complex requests into focused, parallel tasks.";
|
|
@@ -349208,6 +349454,7 @@ function generateSandboxGlobals(options) {
|
|
|
349208
349454
|
executing.add(p5);
|
|
349209
349455
|
results.push(p5);
|
|
349210
349456
|
if (executing.size >= mapConcurrency) {
|
|
349457
|
+
console.error(`[map] Concurrency limit reached (${executing.size}/${mapConcurrency}), waiting for a slot...`);
|
|
349211
349458
|
await Promise.race(executing);
|
|
349212
349459
|
}
|
|
349213
349460
|
}
|
|
@@ -353437,8 +353684,23 @@ __export(ProbeAgent_exports, {
|
|
|
353437
353684
|
ENGINE_ACTIVITY_TIMEOUT_DEFAULT: () => ENGINE_ACTIVITY_TIMEOUT_DEFAULT,
|
|
353438
353685
|
ENGINE_ACTIVITY_TIMEOUT_MAX: () => ENGINE_ACTIVITY_TIMEOUT_MAX,
|
|
353439
353686
|
ENGINE_ACTIVITY_TIMEOUT_MIN: () => ENGINE_ACTIVITY_TIMEOUT_MIN,
|
|
353440
|
-
ProbeAgent: () => ProbeAgent
|
|
353687
|
+
ProbeAgent: () => ProbeAgent,
|
|
353688
|
+
debugLogToolResults: () => debugLogToolResults,
|
|
353689
|
+
debugTruncate: () => debugTruncate
|
|
353441
353690
|
});
|
|
353691
|
+
function debugTruncate(s5, limit = 200) {
|
|
353692
|
+
if (s5.length <= limit) return s5;
|
|
353693
|
+
const half = Math.floor(limit / 2);
|
|
353694
|
+
return s5.substring(0, half) + ` ... [${s5.length} chars] ... ` + s5.substring(s5.length - half);
|
|
353695
|
+
}
|
|
353696
|
+
function debugLogToolResults(toolResults) {
|
|
353697
|
+
if (!toolResults || toolResults.length === 0) return;
|
|
353698
|
+
for (const tr of toolResults) {
|
|
353699
|
+
const argsStr = JSON.stringify(tr.args || {});
|
|
353700
|
+
const resultStr = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result || "");
|
|
353701
|
+
console.log(`[DEBUG] tool: ${tr.toolName} | args: ${debugTruncate(argsStr)} | result: ${debugTruncate(resultStr)}`);
|
|
353702
|
+
}
|
|
353703
|
+
}
|
|
353442
353704
|
var import_dotenv, import_anthropic2, import_openai2, import_google2, import_ai4, import_crypto8, import_events4, import_fs10, import_promises6, import_path15, ENGINE_ACTIVITY_TIMEOUT_DEFAULT, ENGINE_ACTIVITY_TIMEOUT_MIN, ENGINE_ACTIVITY_TIMEOUT_MAX, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
|
|
353443
353705
|
var init_ProbeAgent = __esm({
|
|
353444
353706
|
"src/agent/ProbeAgent.js"() {
|
|
@@ -353558,6 +353820,7 @@ var init_ProbeAgent = __esm({
|
|
|
353558
353820
|
this.enableExecutePlan = !!options.enableExecutePlan;
|
|
353559
353821
|
this.debug = options.debug || process.env.DEBUG === "1";
|
|
353560
353822
|
this.cancelled = false;
|
|
353823
|
+
this._abortController = new AbortController();
|
|
353561
353824
|
this.tracer = options.tracer || null;
|
|
353562
353825
|
this.outline = !!options.outline;
|
|
353563
353826
|
this.searchDelegate = options.searchDelegate !== void 0 ? !!options.searchDelegate : true;
|
|
@@ -353586,6 +353849,7 @@ var init_ProbeAgent = __esm({
|
|
|
353586
353849
|
this.completionPrompt = options.completionPrompt || null;
|
|
353587
353850
|
this.thinkingEffort = options.thinkingEffort || null;
|
|
353588
353851
|
const effectiveAllowedTools = options.disableTools ? [] : options.allowedTools;
|
|
353852
|
+
this._rawAllowedTools = options.allowedTools;
|
|
353589
353853
|
this.allowedTools = this._parseAllowedTools(effectiveAllowedTools);
|
|
353590
353854
|
this.storageAdapter = options.storageAdapter || new InMemoryStorageAdapter();
|
|
353591
353855
|
this.hooks = new HookManager();
|
|
@@ -353728,6 +353992,16 @@ var init_ProbeAgent = __esm({
|
|
|
353728
353992
|
_filterMcpTools(mcpToolNames) {
|
|
353729
353993
|
return mcpToolNames.filter((toolName) => this._isMcpToolAllowed(toolName));
|
|
353730
353994
|
}
|
|
353995
|
+
/**
|
|
353996
|
+
* Check if query tool was explicitly listed in allowedTools (not via wildcard).
|
|
353997
|
+
* Query (ast-grep) is excluded by default because models struggle with AST pattern syntax.
|
|
353998
|
+
* @returns {boolean}
|
|
353999
|
+
* @private
|
|
354000
|
+
*/
|
|
354001
|
+
_isQueryExplicitlyAllowed() {
|
|
354002
|
+
if (!this._rawAllowedTools) return false;
|
|
354003
|
+
return Array.isArray(this._rawAllowedTools) && this._rawAllowedTools.includes("query");
|
|
354004
|
+
}
|
|
353731
354005
|
/**
|
|
353732
354006
|
* Check if tracer is AppTracer (expects sessionId as first param) vs SimpleAppTracer
|
|
353733
354007
|
* @returns {boolean} - True if tracer is AppTracer style (requires sessionId)
|
|
@@ -354003,6 +354277,8 @@ var init_ProbeAgent = __esm({
|
|
|
354003
354277
|
searchDelegateModel: this.searchDelegateModel,
|
|
354004
354278
|
delegationManager: this.delegationManager,
|
|
354005
354279
|
// Per-instance delegation limits
|
|
354280
|
+
parentAbortSignal: this._abortController.signal,
|
|
354281
|
+
// Propagate cancellation to delegations
|
|
354006
354282
|
outputBuffer: this._outputBuffer,
|
|
354007
354283
|
concurrencyLimiter: this.concurrencyLimiter,
|
|
354008
354284
|
// Global AI concurrency limiter
|
|
@@ -354019,7 +354295,7 @@ var init_ProbeAgent = __esm({
|
|
|
354019
354295
|
if (wrappedTools.searchToolInstance && isToolAllowed("search")) {
|
|
354020
354296
|
this.toolImplementations.search = wrappedTools.searchToolInstance;
|
|
354021
354297
|
}
|
|
354022
|
-
if (wrappedTools.queryToolInstance && isToolAllowed("query")) {
|
|
354298
|
+
if (wrappedTools.queryToolInstance && isToolAllowed("query") && this._isQueryExplicitlyAllowed()) {
|
|
354023
354299
|
this.toolImplementations.query = wrappedTools.queryToolInstance;
|
|
354024
354300
|
}
|
|
354025
354301
|
if (wrappedTools.extractToolInstance && isToolAllowed("extract")) {
|
|
@@ -354450,6 +354726,15 @@ var init_ProbeAgent = __esm({
|
|
|
354450
354726
|
}
|
|
354451
354727
|
const controller = new AbortController();
|
|
354452
354728
|
const timeoutState = { timeoutId: null };
|
|
354729
|
+
if (this._abortController.signal.aborted) {
|
|
354730
|
+
controller.abort();
|
|
354731
|
+
} else {
|
|
354732
|
+
const onAgentAbort = () => controller.abort();
|
|
354733
|
+
this._abortController.signal.addEventListener("abort", onAgentAbort, { once: true });
|
|
354734
|
+
controller.signal.addEventListener("abort", () => {
|
|
354735
|
+
this._abortController.signal.removeEventListener("abort", onAgentAbort);
|
|
354736
|
+
}, { once: true });
|
|
354737
|
+
}
|
|
354453
354738
|
if (this.maxOperationTimeout && this.maxOperationTimeout > 0) {
|
|
354454
354739
|
timeoutState.timeoutId = setTimeout(() => {
|
|
354455
354740
|
controller.abort();
|
|
@@ -354753,7 +355038,8 @@ var init_ProbeAgent = __esm({
|
|
|
354753
355038
|
allowEdit: this.allowEdit,
|
|
354754
355039
|
allowedTools: allowedToolsForDelegate,
|
|
354755
355040
|
debug: this.debug,
|
|
354756
|
-
tracer: this.tracer
|
|
355041
|
+
tracer: this.tracer,
|
|
355042
|
+
parentAbortSignal: this._abortController.signal
|
|
354757
355043
|
};
|
|
354758
355044
|
if (this.debug) {
|
|
354759
355045
|
console.log(`[DEBUG] Executing delegate tool`);
|
|
@@ -354948,12 +355234,13 @@ var init_ProbeAgent = __esm({
|
|
|
354948
355234
|
const toolMap = {
|
|
354949
355235
|
search: {
|
|
354950
355236
|
schema: searchSchema,
|
|
354951
|
-
description: "Search code in the repository using keyword queries with Elasticsearch syntax."
|
|
354952
|
-
},
|
|
354953
|
-
query: {
|
|
354954
|
-
schema: querySchema,
|
|
354955
|
-
description: "Search code using ast-grep structural pattern matching."
|
|
355237
|
+
description: this.searchDelegate ? "Search code in the repository by asking a question. Accepts natural language questions \u2014 a subagent breaks them into targeted keyword searches and returns extracted code blocks. Do NOT formulate keyword queries yourself." : "Search code in the repository using keyword queries with Elasticsearch syntax. Handles stemming, case-insensitive matching, and camelCase/snake_case splitting automatically \u2014 do NOT try keyword variations manually."
|
|
354956
355238
|
},
|
|
355239
|
+
// query tool (ast-grep) removed from AI-facing tools — models struggle with pattern syntax
|
|
355240
|
+
// query: {
|
|
355241
|
+
// schema: querySchema,
|
|
355242
|
+
// description: 'Search code using ast-grep structural pattern matching.'
|
|
355243
|
+
// },
|
|
354957
355244
|
extract: {
|
|
354958
355245
|
schema: extractSchema,
|
|
354959
355246
|
description: "Extract code blocks from files based on file paths and optional line numbers."
|
|
@@ -355621,25 +355908,27 @@ ${this.architectureContext.content}
|
|
|
355621
355908
|
} else {
|
|
355622
355909
|
systemPrompt += predefinedPrompts["code-explorer"] + "\n\n";
|
|
355623
355910
|
}
|
|
355911
|
+
const searchToolDesc1 = this.searchDelegate ? '- search: Ask natural language questions to find code (e.g., "How does authentication work?"). A subagent handles keyword searches and returns extracted code blocks. Do NOT formulate keyword queries \u2014 just ask questions.' : "- search: Find code patterns using keyword queries with Elasticsearch syntax. Handles stemming and case variations automatically \u2014 do NOT try manual keyword variations.";
|
|
355624
355912
|
systemPrompt += `You have access to powerful code search and analysis tools through MCP:
|
|
355625
|
-
|
|
355913
|
+
${searchToolDesc1}
|
|
355626
355914
|
- extract: Extract specific code sections with context
|
|
355627
|
-
- query: Use AST patterns for structural code matching
|
|
355628
355915
|
- listFiles: Browse directory contents
|
|
355629
355916
|
- searchFiles: Find files by name patterns`;
|
|
355630
355917
|
if (this.enableBash) {
|
|
355631
355918
|
systemPrompt += `
|
|
355632
355919
|
- bash: Execute bash commands for system operations`;
|
|
355633
355920
|
}
|
|
355634
|
-
const
|
|
355635
|
-
const
|
|
355921
|
+
const searchGuidance1 = this.searchDelegate ? "1. Start with search \u2014 ask a question about what you want to understand. It returns extracted code blocks directly." : "1. Start with search to find relevant code patterns. One search per concept is usually enough \u2014 probe handles stemming and case variations.";
|
|
355922
|
+
const extractGuidance1 = this.searchDelegate ? "2. Use extract only if you need more context or a full file" : "2. Use extract to get detailed context when needed";
|
|
355636
355923
|
systemPrompt += `
|
|
355637
355924
|
|
|
355638
355925
|
When exploring code:
|
|
355639
|
-
${
|
|
355640
|
-
${
|
|
355926
|
+
${searchGuidance1}
|
|
355927
|
+
${extractGuidance1}
|
|
355641
355928
|
3. Prefer focused, specific searches over broad queries
|
|
355642
|
-
4.
|
|
355929
|
+
4. Do NOT repeat the same search or try trivial keyword variations \u2014 probe handles stemming and case variations automatically
|
|
355930
|
+
5. If 2-3 consecutive searches return no results for a concept, stop searching for it \u2014 the term likely does not exist in that codebase
|
|
355931
|
+
6. Combine multiple tools to build complete understanding`;
|
|
355643
355932
|
if (this.allowedFolders && this.allowedFolders.length > 0) {
|
|
355644
355933
|
systemPrompt += `
|
|
355645
355934
|
|
|
@@ -355674,25 +355963,27 @@ Workspace: ${this.allowedFolders.join(", ")}`;
|
|
|
355674
355963
|
} else {
|
|
355675
355964
|
systemPrompt += predefinedPrompts["code-explorer"] + "\n\n";
|
|
355676
355965
|
}
|
|
355966
|
+
const searchToolDesc2 = this.searchDelegate ? '- search: Ask natural language questions to find code (e.g., "How does authentication work?"). A subagent handles keyword searches and returns extracted code blocks. Do NOT formulate keyword queries \u2014 just ask questions.' : "- search: Find code patterns using keyword queries with Elasticsearch syntax. Handles stemming and case variations automatically \u2014 do NOT try manual keyword variations.";
|
|
355677
355967
|
systemPrompt += `You have access to powerful code search and analysis tools through MCP:
|
|
355678
|
-
|
|
355968
|
+
${searchToolDesc2}
|
|
355679
355969
|
- extract: Extract specific code sections with context
|
|
355680
|
-
- query: Use AST patterns for structural code matching
|
|
355681
355970
|
- listFiles: Browse directory contents
|
|
355682
355971
|
- searchFiles: Find files by name patterns`;
|
|
355683
355972
|
if (this.enableBash) {
|
|
355684
355973
|
systemPrompt += `
|
|
355685
355974
|
- bash: Execute bash commands for system operations`;
|
|
355686
355975
|
}
|
|
355687
|
-
const
|
|
355688
|
-
const
|
|
355976
|
+
const searchGuidance2 = this.searchDelegate ? "1. Start with search \u2014 ask a question about what you want to understand. It returns extracted code blocks directly." : "1. Start with search to find relevant code patterns. One search per concept is usually enough \u2014 probe handles stemming and case variations.";
|
|
355977
|
+
const extractGuidance2 = this.searchDelegate ? "2. Use extract only if you need more context or a full file" : "2. Use extract to get detailed context when needed";
|
|
355689
355978
|
systemPrompt += `
|
|
355690
355979
|
|
|
355691
355980
|
When exploring code:
|
|
355692
|
-
${
|
|
355693
|
-
${
|
|
355981
|
+
${searchGuidance2}
|
|
355982
|
+
${extractGuidance2}
|
|
355694
355983
|
3. Prefer focused, specific searches over broad queries
|
|
355695
|
-
4.
|
|
355984
|
+
4. Do NOT repeat the same search or try trivial keyword variations \u2014 probe handles stemming and case variations automatically
|
|
355985
|
+
5. If 2-3 consecutive searches return no results for a concept, stop searching for it \u2014 the term likely does not exist in that codebase
|
|
355986
|
+
6. Combine multiple tools to build complete understanding`;
|
|
355696
355987
|
if (this.allowedFolders && this.allowedFolders.length > 0) {
|
|
355697
355988
|
systemPrompt += `
|
|
355698
355989
|
|
|
@@ -355743,10 +356034,10 @@ Workspace: ${this.allowedFolders.join(", ")}`;
|
|
|
355743
356034
|
Follow these instructions carefully:
|
|
355744
356035
|
1. Analyze the user's request.
|
|
355745
356036
|
2. Use the available tools step-by-step to fulfill the request.
|
|
355746
|
-
3. You should always prefer the search tool for code-related questions.${this.searchDelegate ? "
|
|
356037
|
+
3. You should always prefer the search tool for code-related questions.${this.searchDelegate ? " Ask natural language questions \u2014 the search subagent handles keyword formulation and returns extracted code blocks. Use extract only to expand context or read full files." : " Search handles stemming and case variations automatically \u2014 do NOT try keyword variations manually. Read full files only if really necessary."}
|
|
355747
356038
|
4. Ensure to get really deep and understand the full picture before answering.
|
|
355748
356039
|
5. Once the task is fully completed, use the attempt_completion tool to provide the final result.
|
|
355749
|
-
6. Prefer concise and focused search queries. Use specific keywords and phrases to narrow down results
|
|
356040
|
+
6. ${this.searchDelegate ? "Ask clear, specific questions when searching. Each search should target a distinct concept or question." : "Prefer concise and focused search queries. Use specific keywords and phrases to narrow down results."}${this.allowEdit ? `
|
|
355750
356041
|
7. When modifying files, choose the appropriate tool:
|
|
355751
356042
|
- Use 'edit' for all code modifications:
|
|
355752
356043
|
* PREFERRED: Use start_line (and optionally end_line) for line-targeted editing \u2014 this is the safest and most precise approach.${this.hashLines ? ' Use the line:hash references from extract/search output (e.g. "42:ab") for integrity verification.' : ""} Always use extract first to see line numbers${this.hashLines ? " and hashes" : ""}, then edit by line reference.
|
|
@@ -356070,6 +356361,10 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
356070
356361
|
completionResult = result;
|
|
356071
356362
|
completionAttempted = true;
|
|
356072
356363
|
}, toolContext);
|
|
356364
|
+
if (this.debug) {
|
|
356365
|
+
const toolNames = Object.keys(tools2);
|
|
356366
|
+
console.log(`[DEBUG] Agent tools registered (${toolNames.length}): ${toolNames.join(", ")}`);
|
|
356367
|
+
}
|
|
356073
356368
|
let maxResponseTokens = this.maxResponseTokens;
|
|
356074
356369
|
if (!maxResponseTokens) {
|
|
356075
356370
|
maxResponseTokens = 4e3;
|
|
@@ -356109,6 +356404,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
356109
356404
|
}
|
|
356110
356405
|
if (this.debug) {
|
|
356111
356406
|
console.log(`[DEBUG] Step ${currentIteration}/${maxIterations} finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
356407
|
+
debugLogToolResults(toolResults);
|
|
356112
356408
|
}
|
|
356113
356409
|
}
|
|
356114
356410
|
};
|
|
@@ -356265,6 +356561,7 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
356265
356561
|
}
|
|
356266
356562
|
if (this.debug) {
|
|
356267
356563
|
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
356564
|
+
debugLogToolResults(toolResults);
|
|
356268
356565
|
}
|
|
356269
356566
|
}
|
|
356270
356567
|
};
|
|
@@ -356975,6 +357272,9 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
356975
357272
|
* Clean up resources (including MCP connections)
|
|
356976
357273
|
*/
|
|
356977
357274
|
async cleanup() {
|
|
357275
|
+
if (!this._abortController.signal.aborted) {
|
|
357276
|
+
this._abortController.abort();
|
|
357277
|
+
}
|
|
356978
357278
|
if (this.mcpBridge) {
|
|
356979
357279
|
try {
|
|
356980
357280
|
await this.mcpBridge.cleanup();
|
|
@@ -356998,14 +357298,25 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
356998
357298
|
this.clearHistory();
|
|
356999
357299
|
}
|
|
357000
357300
|
/**
|
|
357001
|
-
* Cancel the current request
|
|
357301
|
+
* Cancel the current request and all in-flight delegations.
|
|
357302
|
+
* Aborts the internal AbortController so streamText, subagents,
|
|
357303
|
+
* and any code checking the signal will stop.
|
|
357002
357304
|
*/
|
|
357003
357305
|
cancel() {
|
|
357004
357306
|
this.cancelled = true;
|
|
357307
|
+
this._abortController.abort();
|
|
357005
357308
|
if (this.debug) {
|
|
357006
357309
|
console.log(`[DEBUG] Agent cancelled for session ${this.sessionId}`);
|
|
357007
357310
|
}
|
|
357008
357311
|
}
|
|
357312
|
+
/**
|
|
357313
|
+
* Get the abort signal for this agent.
|
|
357314
|
+
* Delegations and subagents should check this signal.
|
|
357315
|
+
* @returns {AbortSignal}
|
|
357316
|
+
*/
|
|
357317
|
+
get abortSignal() {
|
|
357318
|
+
return this._abortController.signal;
|
|
357319
|
+
}
|
|
357009
357320
|
};
|
|
357010
357321
|
}
|
|
357011
357322
|
});
|
|
@@ -357038,12 +357349,17 @@ async function delegate({
|
|
|
357038
357349
|
mcpConfigPath = null,
|
|
357039
357350
|
delegationManager = null,
|
|
357040
357351
|
// Optional per-instance manager, falls back to default singleton
|
|
357041
|
-
concurrencyLimiter = null
|
|
357352
|
+
concurrencyLimiter = null,
|
|
357042
357353
|
// Optional global AI concurrency limiter
|
|
357354
|
+
parentAbortSignal = null
|
|
357355
|
+
// Optional AbortSignal from parent to cancel this delegation
|
|
357043
357356
|
}) {
|
|
357044
357357
|
if (!task || typeof task !== "string") {
|
|
357045
357358
|
throw new Error("Task parameter is required and must be a string");
|
|
357046
357359
|
}
|
|
357360
|
+
if (parentAbortSignal?.aborted) {
|
|
357361
|
+
throw new Error("Delegation cancelled: parent operation was aborted");
|
|
357362
|
+
}
|
|
357047
357363
|
const hasExplicitTimeout = Object.prototype.hasOwnProperty.call(arguments?.[0] ?? {}, "timeout");
|
|
357048
357364
|
if (!hasExplicitTimeout) {
|
|
357049
357365
|
const envTimeoutMs = parseInt(process.env.DELEGATION_TIMEOUT_MS || "", 10);
|
|
@@ -357128,12 +357444,37 @@ async function delegate({
|
|
|
357128
357444
|
}
|
|
357129
357445
|
const timeoutPromise = new Promise((_, reject2) => {
|
|
357130
357446
|
timeoutId = setTimeout(() => {
|
|
357447
|
+
subagent.cancel();
|
|
357131
357448
|
reject2(new Error(`Delegation timed out after ${timeout} seconds`));
|
|
357132
357449
|
}, timeout * 1e3);
|
|
357133
357450
|
});
|
|
357451
|
+
let parentAbortHandler;
|
|
357452
|
+
const parentAbortPromise = new Promise((_, reject2) => {
|
|
357453
|
+
if (parentAbortSignal) {
|
|
357454
|
+
if (parentAbortSignal.aborted) {
|
|
357455
|
+
subagent.cancel();
|
|
357456
|
+
reject2(new Error("Delegation cancelled: parent operation was aborted"));
|
|
357457
|
+
return;
|
|
357458
|
+
}
|
|
357459
|
+
parentAbortHandler = () => {
|
|
357460
|
+
subagent.cancel();
|
|
357461
|
+
reject2(new Error("Delegation cancelled: parent operation was aborted"));
|
|
357462
|
+
};
|
|
357463
|
+
parentAbortSignal.addEventListener("abort", parentAbortHandler, { once: true });
|
|
357464
|
+
}
|
|
357465
|
+
});
|
|
357134
357466
|
const answerOptions = schema ? { schema } : void 0;
|
|
357135
357467
|
const answerPromise = answerOptions ? subagent.answer(task, [], answerOptions) : subagent.answer(task);
|
|
357136
|
-
const
|
|
357468
|
+
const racers = [answerPromise, timeoutPromise];
|
|
357469
|
+
if (parentAbortSignal) racers.push(parentAbortPromise);
|
|
357470
|
+
let response;
|
|
357471
|
+
try {
|
|
357472
|
+
response = await Promise.race(racers);
|
|
357473
|
+
} finally {
|
|
357474
|
+
if (parentAbortHandler && parentAbortSignal) {
|
|
357475
|
+
parentAbortSignal.removeEventListener("abort", parentAbortHandler);
|
|
357476
|
+
}
|
|
357477
|
+
}
|
|
357137
357478
|
if (timeoutId !== null) {
|
|
357138
357479
|
clearTimeout(timeoutId);
|
|
357139
357480
|
timeoutId = null;
|
|
@@ -357289,10 +357630,9 @@ var init_delegate = __esm({
|
|
|
357289
357630
|
if (this.tryAcquire(parentSessionId)) {
|
|
357290
357631
|
return true;
|
|
357291
357632
|
}
|
|
357292
|
-
|
|
357293
|
-
console.error(`[DelegationManager] Slot unavailable (${this.globalActive}/${this.maxConcurrent}), queuing... (queue size: ${this.waitQueue.length}, timeout: ${effectiveTimeout}ms)`);
|
|
357294
|
-
}
|
|
357633
|
+
console.error(`[DelegationManager] Slot unavailable (${this.globalActive}/${this.maxConcurrent}), queuing... (queue size: ${this.waitQueue.length + 1}, timeout: ${effectiveTimeout}ms)`);
|
|
357295
357634
|
return new Promise((resolve8, reject2) => {
|
|
357635
|
+
const queuedAt = Date.now();
|
|
357296
357636
|
const entry = {
|
|
357297
357637
|
resolve: null,
|
|
357298
357638
|
// Will be wrapped below
|
|
@@ -357300,20 +357640,23 @@ var init_delegate = __esm({
|
|
|
357300
357640
|
// Will be wrapped below
|
|
357301
357641
|
parentSessionId,
|
|
357302
357642
|
debug,
|
|
357303
|
-
queuedAt
|
|
357304
|
-
timeoutId: null
|
|
357643
|
+
queuedAt,
|
|
357644
|
+
timeoutId: null,
|
|
357645
|
+
reminderId: null
|
|
357305
357646
|
};
|
|
357306
357647
|
let settled = false;
|
|
357307
357648
|
entry.resolve = (value) => {
|
|
357308
357649
|
if (settled) return;
|
|
357309
357650
|
settled = true;
|
|
357310
357651
|
if (entry.timeoutId) clearTimeout(entry.timeoutId);
|
|
357652
|
+
if (entry.reminderId) clearInterval(entry.reminderId);
|
|
357311
357653
|
resolve8(value);
|
|
357312
357654
|
};
|
|
357313
357655
|
entry.reject = (error2) => {
|
|
357314
357656
|
if (settled) return;
|
|
357315
357657
|
settled = true;
|
|
357316
357658
|
if (entry.timeoutId) clearTimeout(entry.timeoutId);
|
|
357659
|
+
if (entry.reminderId) clearInterval(entry.reminderId);
|
|
357317
357660
|
reject2(error2);
|
|
357318
357661
|
};
|
|
357319
357662
|
if (effectiveTimeout > 0) {
|
|
@@ -357325,6 +357668,13 @@ var init_delegate = __esm({
|
|
|
357325
357668
|
entry.reject(new Error(`Delegation queue timeout: waited ${effectiveTimeout}ms for an available slot`));
|
|
357326
357669
|
}, effectiveTimeout);
|
|
357327
357670
|
}
|
|
357671
|
+
entry.reminderId = setInterval(() => {
|
|
357672
|
+
const waitedSeconds = Math.round((Date.now() - queuedAt) / 1e3);
|
|
357673
|
+
console.error(`[DelegationManager] Still waiting for slot (${waitedSeconds}s). ${this.globalActive}/${this.maxConcurrent} active, ${this.waitQueue.length} queued.`);
|
|
357674
|
+
}, 15e3);
|
|
357675
|
+
if (entry.reminderId.unref) {
|
|
357676
|
+
entry.reminderId.unref();
|
|
357677
|
+
}
|
|
357328
357678
|
this.waitQueue.push(entry);
|
|
357329
357679
|
});
|
|
357330
357680
|
}
|
|
@@ -357363,18 +357713,14 @@ var init_delegate = __esm({
|
|
|
357363
357713
|
const sessionData = this.sessionDelegations.get(parentSessionId);
|
|
357364
357714
|
const sessionCount = sessionData?.count || 0;
|
|
357365
357715
|
if (sessionCount >= this.maxPerSession) {
|
|
357366
|
-
|
|
357367
|
-
console.error(`[DelegationManager] Session limit (${this.maxPerSession}) reached for queued item, rejecting`);
|
|
357368
|
-
}
|
|
357716
|
+
console.error(`[DelegationManager] Session limit (${this.maxPerSession}) reached for queued item, rejecting`);
|
|
357369
357717
|
toReject.push({ reject: reject2, error: new Error(`Maximum delegations per session (${this.maxPerSession}) reached for session ${parentSessionId}`) });
|
|
357370
357718
|
continue;
|
|
357371
357719
|
}
|
|
357372
357720
|
}
|
|
357373
357721
|
this._incrementCounters(parentSessionId);
|
|
357374
|
-
|
|
357375
|
-
|
|
357376
|
-
console.error(`[DelegationManager] Granted slot from queue (waited ${waitTime}ms). Active: ${this.globalActive}/${this.maxConcurrent}`);
|
|
357377
|
-
}
|
|
357722
|
+
const waitTime = Date.now() - queuedAt;
|
|
357723
|
+
console.error(`[DelegationManager] Granted slot from queue (waited ${waitTime}ms). Active: ${this.globalActive}/${this.maxConcurrent}`);
|
|
357378
357724
|
toResolve.push(resolve8);
|
|
357379
357725
|
}
|
|
357380
357726
|
if (toResolve.length > 0 || toReject.length > 0) {
|
|
@@ -357424,6 +357770,9 @@ var init_delegate = __esm({
|
|
|
357424
357770
|
if (entry.timeoutId) {
|
|
357425
357771
|
clearTimeout(entry.timeoutId);
|
|
357426
357772
|
}
|
|
357773
|
+
if (entry.reminderId) {
|
|
357774
|
+
clearInterval(entry.reminderId);
|
|
357775
|
+
}
|
|
357427
357776
|
if (entry.reject) {
|
|
357428
357777
|
entry.reject(new Error("DelegationManager was cleaned up"));
|
|
357429
357778
|
}
|
|
@@ -357546,8 +357895,9 @@ Instructions:
|
|
|
357546
357895
|
promptType: "code-researcher",
|
|
357547
357896
|
allowedTools: ["extract"],
|
|
357548
357897
|
maxIterations: 5,
|
|
357549
|
-
delegationManager: options.delegationManager
|
|
357898
|
+
delegationManager: options.delegationManager,
|
|
357550
357899
|
// Per-instance delegation limits
|
|
357900
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
357551
357901
|
// timeout removed - inherit default from delegate (300s)
|
|
357552
357902
|
});
|
|
357553
357903
|
return { chunk, result };
|
|
@@ -357567,16 +357917,12 @@ async function processChunksParallel(chunks, extractionPrompt, maxWorkers, optio
|
|
|
357567
357917
|
return result;
|
|
357568
357918
|
});
|
|
357569
357919
|
active.add(promise);
|
|
357570
|
-
|
|
357571
|
-
console.error(`[analyze_all] Started processing chunk ${chunk.id}/${chunk.total}`);
|
|
357572
|
-
}
|
|
357920
|
+
console.error(`[analyze_all] Started processing chunk ${chunk.id}/${chunk.total}`);
|
|
357573
357921
|
}
|
|
357574
357922
|
if (active.size > 0) {
|
|
357575
357923
|
const result = await Promise.race(active);
|
|
357576
357924
|
results.push(result);
|
|
357577
|
-
|
|
357578
|
-
console.error(`[analyze_all] Completed chunk ${result.chunk.id}/${result.chunk.total}`);
|
|
357579
|
-
}
|
|
357925
|
+
console.error(`[analyze_all] Completed chunk ${result.chunk.id}/${result.chunk.total}`);
|
|
357580
357926
|
}
|
|
357581
357927
|
}
|
|
357582
357928
|
results.sort((a5, b5) => a5.chunk.id - b5.chunk.id);
|
|
@@ -357646,8 +357992,9 @@ Organize all findings into clear categories with items listed under each.${compl
|
|
|
357646
357992
|
promptType: "code-researcher",
|
|
357647
357993
|
allowedTools: [],
|
|
357648
357994
|
maxIterations: 5,
|
|
357649
|
-
delegationManager: options.delegationManager
|
|
357995
|
+
delegationManager: options.delegationManager,
|
|
357650
357996
|
// Per-instance delegation limits
|
|
357997
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
357651
357998
|
// timeout removed - inherit default from delegate (300s)
|
|
357652
357999
|
});
|
|
357653
358000
|
return result;
|
|
@@ -357711,8 +358058,9 @@ CRITICAL: Do NOT guess keywords. Actually run searches and see what returns resu
|
|
|
357711
358058
|
promptType: "code-researcher",
|
|
357712
358059
|
// Full tool access for exploration and experimentation
|
|
357713
358060
|
maxIterations: 15,
|
|
357714
|
-
delegationManager: options.delegationManager
|
|
358061
|
+
delegationManager: options.delegationManager,
|
|
357715
358062
|
// Per-instance delegation limits
|
|
358063
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
357716
358064
|
// timeout removed - inherit default from delegate (300s)
|
|
357717
358065
|
});
|
|
357718
358066
|
const plan = parsePlanningResult(stripResultTags(result));
|
|
@@ -357769,8 +358117,9 @@ When done, use the attempt_completion tool with your answer as the result.`;
|
|
|
357769
358117
|
promptType: "code-researcher",
|
|
357770
358118
|
allowedTools: [],
|
|
357771
358119
|
maxIterations: 5,
|
|
357772
|
-
delegationManager: options.delegationManager
|
|
358120
|
+
delegationManager: options.delegationManager,
|
|
357773
358121
|
// Per-instance delegation limits
|
|
358122
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
357774
358123
|
// timeout removed - inherit default from delegate (300s)
|
|
357775
358124
|
});
|
|
357776
358125
|
return stripResultTags(result);
|
|
@@ -358083,11 +358432,41 @@ function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, all
|
|
|
358083
358432
|
"- extract: Verify code snippets to ensure targets are actually relevant before including them.",
|
|
358084
358433
|
"- listFiles: Understand directory structure to find where relevant code might live.",
|
|
358085
358434
|
"",
|
|
358086
|
-
"
|
|
358435
|
+
"CRITICAL - How probe search works (do NOT ignore):",
|
|
358436
|
+
"- By default (exact=false), probe ALREADY handles stemming, case-insensitive matching, and camelCase/snake_case splitting.",
|
|
358437
|
+
'- Searching "allowed_ips" ALREADY matches "AllowedIPs", "allowedIps", "allowed_ips", etc. Do NOT manually try case/style variations.',
|
|
358438
|
+
'- Searching "getUserData" ALREADY matches "get", "user", "data" and their variations.',
|
|
358439
|
+
"- NEVER repeat the same search query \u2014 you will get the same results.",
|
|
358440
|
+
"- NEVER search trivial variations of the same keyword (e.g., AllowedIPs then allowedIps then allowed_ips). This is wasteful \u2014 probe handles it.",
|
|
358441
|
+
"- If a search returns no results, the term likely does not exist in that path. Try a genuinely DIFFERENT keyword or concept, not a variation.",
|
|
358442
|
+
"- If 2-3 consecutive searches return no results for a concept, STOP searching for it and move on.",
|
|
358443
|
+
"",
|
|
358444
|
+
"GOOD search strategy (do this):",
|
|
358445
|
+
' Query: "How does authentication work and how are sessions managed?"',
|
|
358446
|
+
' \u2192 search "authentication" \u2192 search "session management" (two different concepts)',
|
|
358447
|
+
' Query: "Find the IP allowlist middleware"',
|
|
358448
|
+
' \u2192 search "allowlist middleware" (one search, probe handles IP/ip/Ip variations)',
|
|
358449
|
+
' Query: "How does BM25 scoring work with SIMD optimization?"',
|
|
358450
|
+
' \u2192 search "BM25 scoring" \u2192 search "SIMD optimization" (two different concepts)',
|
|
358451
|
+
"",
|
|
358452
|
+
"BAD search strategy (never do this):",
|
|
358453
|
+
' \u2192 search "AllowedIPs" \u2192 search "allowedIps" \u2192 search "allowed_ips" (WRONG: these are trivial case variations, probe handles them)',
|
|
358454
|
+
' \u2192 search "CIDR" \u2192 search "cidr" \u2192 search "Cidr" \u2192 search "*cidr*" (WRONG: same keyword repeated with variations)',
|
|
358455
|
+
' \u2192 search "error handling" \u2192 search "error handling" \u2192 search "error handling" (WRONG: repeating exact same query)',
|
|
358456
|
+
"",
|
|
358457
|
+
"Keyword tips:",
|
|
358458
|
+
"- Common programming keywords are filtered as stopwords when unquoted: function, class, return, new, struct, impl, var, let, const, etc.",
|
|
358459
|
+
'- Avoid searching for these alone \u2014 combine with a specific term (e.g., "middleware function" is fine, "function" alone is too generic).',
|
|
358460
|
+
'- To bypass stopword filtering: wrap terms in quotes ("return", "struct") or set exact=true. Both disable stemming and splitting too.',
|
|
358461
|
+
"- Multiple words without operators use OR logic: foo bar = foo OR bar. Use AND explicitly if you need both: foo AND bar.",
|
|
358462
|
+
'- camelCase terms are split: getUserData becomes "get", "user", "data" \u2014 so one search covers all naming styles.',
|
|
358463
|
+
"",
|
|
358464
|
+
"Strategy:",
|
|
358087
358465
|
"1. Analyze the query - identify key concepts, entities, and relationships",
|
|
358088
|
-
|
|
358089
|
-
"3.
|
|
358090
|
-
"4.
|
|
358466
|
+
"2. Run ONE focused search per concept with the most natural keyword. Trust probe to handle variations.",
|
|
358467
|
+
"3. If a search returns results, use extract to verify relevance",
|
|
358468
|
+
"4. Only try a different keyword if the first one returned irrelevant results (not if it returned no results \u2014 that means the concept is absent)",
|
|
358469
|
+
"5. Combine all relevant targets in your final response",
|
|
358091
358470
|
"",
|
|
358092
358471
|
`Query: ${searchQuery}`,
|
|
358093
358472
|
`Search path(s): ${searchPath}`,
|
|
@@ -358140,9 +358519,12 @@ var init_vercel = __esm({
|
|
|
358140
358519
|
}
|
|
358141
358520
|
return result;
|
|
358142
358521
|
};
|
|
358522
|
+
const previousSearches = /* @__PURE__ */ new Set();
|
|
358523
|
+
const paginationCounts = /* @__PURE__ */ new Map();
|
|
358524
|
+
const MAX_PAGES_PER_QUERY = 3;
|
|
358143
358525
|
return (0, import_ai5.tool)({
|
|
358144
358526
|
name: "search",
|
|
358145
|
-
description: searchDelegate ?
|
|
358527
|
+
description: searchDelegate ? searchDelegateDescription : searchDescription,
|
|
358146
358528
|
inputSchema: searchSchema,
|
|
358147
358529
|
execute: async ({ query: searchQuery, path: path9, allow_tests, exact, maxTokens: paramMaxTokens, language, session, nextPage }) => {
|
|
358148
358530
|
const effectiveMaxTokens = paramMaxTokens || maxTokens;
|
|
@@ -358180,6 +358562,26 @@ var init_vercel = __esm({
|
|
|
358180
358562
|
return await search(searchOptions);
|
|
358181
358563
|
};
|
|
358182
358564
|
if (!searchDelegate) {
|
|
358565
|
+
const searchKey = `${searchQuery}::${searchPath}::${exact || false}`;
|
|
358566
|
+
if (!nextPage) {
|
|
358567
|
+
if (previousSearches.has(searchKey)) {
|
|
358568
|
+
if (debug) {
|
|
358569
|
+
console.error(`[DEDUP] Blocked duplicate search: "${searchQuery}" in "${searchPath}"`);
|
|
358570
|
+
}
|
|
358571
|
+
return "DUPLICATE SEARCH BLOCKED: You already searched for this exact query in this path. Do NOT repeat the same search. If you need more results, set nextPage=true with the session ID from the previous search. Otherwise, try a genuinely different keyword, use extract to examine results you already found, or use attempt_completion if you have enough information.";
|
|
358572
|
+
}
|
|
358573
|
+
previousSearches.add(searchKey);
|
|
358574
|
+
paginationCounts.set(searchKey, 0);
|
|
358575
|
+
} else {
|
|
358576
|
+
const pageCount = (paginationCounts.get(searchKey) || 0) + 1;
|
|
358577
|
+
paginationCounts.set(searchKey, pageCount);
|
|
358578
|
+
if (pageCount > MAX_PAGES_PER_QUERY) {
|
|
358579
|
+
if (debug) {
|
|
358580
|
+
console.error(`[DEDUP] Blocked excessive pagination (page ${pageCount}/${MAX_PAGES_PER_QUERY}): "${searchQuery}" in "${searchPath}"`);
|
|
358581
|
+
}
|
|
358582
|
+
return `PAGINATION LIMIT REACHED: You have already retrieved ${MAX_PAGES_PER_QUERY} pages of results for this query. You have enough results \u2014 use extract to examine specific files, or use attempt_completion to return your findings.`;
|
|
358583
|
+
}
|
|
358584
|
+
}
|
|
358183
358585
|
try {
|
|
358184
358586
|
const result = maybeAnnotate(await runRawSearch());
|
|
358185
358587
|
if (options.fileTracker && typeof result === "string") {
|
|
@@ -358218,7 +358620,8 @@ var init_vercel = __esm({
|
|
|
358218
358620
|
promptType: "code-searcher",
|
|
358219
358621
|
allowedTools: ["search", "extract", "listFiles", "attempt_completion"],
|
|
358220
358622
|
searchDelegate: false,
|
|
358221
|
-
schema: CODE_SEARCH_SCHEMA
|
|
358623
|
+
schema: CODE_SEARCH_SCHEMA,
|
|
358624
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
358222
358625
|
});
|
|
358223
358626
|
const delegateResult = options.tracer?.withSpan ? await options.tracer.withSpan("search.delegate", runDelegation, {
|
|
358224
358627
|
"search.query": searchQuery,
|
|
@@ -358432,7 +358835,7 @@ var init_vercel = __esm({
|
|
|
358432
358835
|
name: "delegate",
|
|
358433
358836
|
description: delegateDescription,
|
|
358434
358837
|
inputSchema: delegateSchema,
|
|
358435
|
-
execute: async ({ task, currentIteration, maxIterations, parentSessionId, path: path9, provider, model, tracer, searchDelegate }) => {
|
|
358838
|
+
execute: async ({ task, currentIteration, maxIterations, parentSessionId, path: path9, provider, model, tracer, searchDelegate, parentAbortSignal }) => {
|
|
358436
358839
|
if (!task || typeof task !== "string") {
|
|
358437
358840
|
throw new Error("Task parameter is required and must be a non-empty string");
|
|
358438
358841
|
}
|
|
@@ -358490,8 +358893,9 @@ var init_vercel = __esm({
|
|
|
358490
358893
|
enableMcp,
|
|
358491
358894
|
mcpConfig,
|
|
358492
358895
|
mcpConfigPath,
|
|
358493
|
-
delegationManager
|
|
358896
|
+
delegationManager,
|
|
358494
358897
|
// Per-instance delegation limits
|
|
358898
|
+
parentAbortSignal
|
|
358495
358899
|
});
|
|
358496
358900
|
return result;
|
|
358497
358901
|
}
|
|
@@ -358529,8 +358933,9 @@ var init_vercel = __esm({
|
|
|
358529
358933
|
provider: options.provider,
|
|
358530
358934
|
model: options.model,
|
|
358531
358935
|
tracer: options.tracer,
|
|
358532
|
-
delegationManager
|
|
358936
|
+
delegationManager,
|
|
358533
358937
|
// Per-instance delegation limits
|
|
358938
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
358534
358939
|
});
|
|
358535
358940
|
return result;
|
|
358536
358941
|
} catch (error2) {
|
|
@@ -395746,7 +396151,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"100":"Continue","101":"Switching Pro
|
|
|
395746
396151
|
/***/ ((module) => {
|
|
395747
396152
|
|
|
395748
396153
|
"use strict";
|
|
395749
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.
|
|
396154
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.166","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-rc280","@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"]}}');
|
|
395750
396155
|
|
|
395751
396156
|
/***/ })
|
|
395752
396157
|
|