@probelabs/visor 0.1.87 → 0.1.89

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.
@@ -59,6 +59,8 @@ interface ReviewIssue {
59
59
  interface ReviewSummary {
60
60
  issues?: ReviewIssue[];
61
61
  debug?: AIDebugInfo;
62
+ /** Session ID created for this check (for cleanup tracking) */
63
+ sessionId?: string;
62
64
  }
63
65
 
64
66
  /**
@@ -262,6 +264,8 @@ interface CheckConfig {
262
264
  if?: string;
263
265
  /** Check name to reuse AI session from, or true to use first dependency (only works with depends_on) */
264
266
  reuse_ai_session?: string | boolean;
267
+ /** How to reuse AI session: 'clone' (default, copy history) or 'append' (share history) */
268
+ session_mode?: 'clone' | 'append';
265
269
  /** Simple fail condition - fails check if expression evaluates to true */
266
270
  fail_if?: string;
267
271
  /** Check-specific failure conditions - optional (deprecated, use fail_if) */
package/dist/sdk/sdk.d.ts CHANGED
@@ -59,6 +59,8 @@ interface ReviewIssue {
59
59
  interface ReviewSummary {
60
60
  issues?: ReviewIssue[];
61
61
  debug?: AIDebugInfo;
62
+ /** Session ID created for this check (for cleanup tracking) */
63
+ sessionId?: string;
62
64
  }
63
65
 
64
66
  /**
@@ -262,6 +264,8 @@ interface CheckConfig {
262
264
  if?: string;
263
265
  /** Check name to reuse AI session from, or true to use first dependency (only works with depends_on) */
264
266
  reuse_ai_session?: string | boolean;
267
+ /** How to reuse AI session: 'clone' (default, copy history) or 'append' (share history) */
268
+ session_mode?: 'clone' | 'append';
265
269
  /** Simple fail condition - fails check if expression evaluates to true */
266
270
  fail_if?: string;
267
271
  /** Check-specific failure conditions - optional (deprecated, use fail_if) */
package/dist/sdk/sdk.js CHANGED
@@ -400,6 +400,47 @@ var init_session_registry = __esm({
400
400
  hasSession(sessionId) {
401
401
  return this.sessions.has(sessionId);
402
402
  }
403
+ /**
404
+ * Clone a session with a new session ID
405
+ * Creates a new ProbeAgent with a copy of the conversation history
406
+ */
407
+ async cloneSession(sourceSessionId, newSessionId) {
408
+ const sourceAgent = this.sessions.get(sourceSessionId);
409
+ if (!sourceAgent) {
410
+ console.error(`\u26A0\uFE0F Cannot clone session: ${sourceSessionId} not found`);
411
+ return void 0;
412
+ }
413
+ try {
414
+ const sourceHistory = sourceAgent.conversationHistory || [];
415
+ const sourceOptions = sourceAgent.options || {};
416
+ const { ProbeAgent: ProbeAgentClass } = await import("@probelabs/probe");
417
+ const clonedAgent = new ProbeAgentClass({
418
+ ...sourceOptions,
419
+ sessionId: newSessionId
420
+ });
421
+ if (sourceHistory.length > 0) {
422
+ try {
423
+ const deepClonedHistory = JSON.parse(JSON.stringify(sourceHistory));
424
+ clonedAgent.conversationHistory = deepClonedHistory;
425
+ console.error(
426
+ `\u{1F4CB} Cloned session ${sourceSessionId} \u2192 ${newSessionId} (${sourceHistory.length} messages, deep copy)`
427
+ );
428
+ } catch (cloneError) {
429
+ console.error(
430
+ `\u26A0\uFE0F Warning: Deep clone failed for session ${sourceSessionId}, using shallow copy: ${cloneError}`
431
+ );
432
+ clonedAgent.conversationHistory = [...sourceHistory];
433
+ }
434
+ } else {
435
+ console.error(`\u{1F4CB} Cloned session ${sourceSessionId} \u2192 ${newSessionId} (no history)`);
436
+ }
437
+ this.registerSession(newSessionId, clonedAgent);
438
+ return clonedAgent;
439
+ } catch (error) {
440
+ console.error(`\u26A0\uFE0F Failed to clone session ${sourceSessionId}: ${error}`);
441
+ return void 0;
442
+ }
443
+ }
403
444
  /**
404
445
  * Register process exit handlers to cleanup sessions on exit
405
446
  */
@@ -671,8 +712,9 @@ var init_ai_review_service = __esm({
671
712
  }
672
713
  /**
673
714
  * Execute AI review using session reuse - reuses an existing ProbeAgent session
715
+ * @param sessionMode - 'clone' (default) clones history, 'append' shares history
674
716
  */
675
- async executeReviewWithSessionReuse(prInfo, customPrompt, parentSessionId, schema, checkName) {
717
+ async executeReviewWithSessionReuse(prInfo, customPrompt, parentSessionId, schema, checkName, sessionMode = "clone") {
676
718
  const startTime = Date.now();
677
719
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
678
720
  const existingAgent = this.sessionRegistry.getSession(parentSessionId);
@@ -682,7 +724,24 @@ var init_ai_review_service = __esm({
682
724
  );
683
725
  }
684
726
  const prompt = await this.buildCustomPrompt(prInfo, customPrompt, schema);
685
- log(`\u{1F504} Reusing AI session ${parentSessionId} for review...`);
727
+ let agentToUse;
728
+ let currentSessionId;
729
+ if (sessionMode === "clone") {
730
+ currentSessionId = `${parentSessionId}-clone-${Date.now()}`;
731
+ log(`\u{1F4CB} Cloning AI session ${parentSessionId} \u2192 ${currentSessionId}...`);
732
+ const clonedAgent = await this.sessionRegistry.cloneSession(
733
+ parentSessionId,
734
+ currentSessionId
735
+ );
736
+ if (!clonedAgent) {
737
+ throw new Error(`Failed to clone session ${parentSessionId}. Falling back to append mode.`);
738
+ }
739
+ agentToUse = clonedAgent;
740
+ } else {
741
+ log(`\u{1F504} Appending to AI session ${parentSessionId} (shared history)...`);
742
+ agentToUse = existingAgent;
743
+ currentSessionId = parentSessionId;
744
+ }
686
745
  log(`\u{1F527} Debug: Raw schema parameter: ${JSON.stringify(schema)} (type: ${typeof schema})`);
687
746
  log(`Schema type: ${schema || "none (no schema)"}`);
688
747
  let debugInfo;
@@ -706,7 +765,7 @@ var init_ai_review_service = __esm({
706
765
  }
707
766
  try {
708
767
  const { response, effectiveSchema } = await this.callProbeAgentWithExistingSession(
709
- existingAgent,
768
+ agentToUse,
710
769
  prompt,
711
770
  schema,
712
771
  debugInfo,
@@ -722,6 +781,9 @@ var init_ai_review_service = __esm({
722
781
  if (debugInfo) {
723
782
  result.debug = debugInfo;
724
783
  }
784
+ if (sessionMode === "clone" && currentSessionId !== parentSessionId) {
785
+ result.sessionId = currentSessionId;
786
+ }
725
787
  return result;
726
788
  } catch (error) {
727
789
  if (debugInfo) {
@@ -2714,9 +2776,10 @@ var init_ai_check_provider = __esm({
2714
2776
  }
2715
2777
  let result;
2716
2778
  if (sessionInfo?.reuseSession && sessionInfo.parentSessionId) {
2779
+ const sessionMode = config.session_mode || "clone";
2717
2780
  if (aiConfig.debug) {
2718
2781
  console.error(
2719
- `\u{1F504} Debug: Using session reuse with parent session: ${sessionInfo.parentSessionId}`
2782
+ `\u{1F504} Debug: Using session reuse with parent session: ${sessionInfo.parentSessionId} (mode: ${sessionMode})`
2720
2783
  );
2721
2784
  }
2722
2785
  result = await service.executeReviewWithSessionReuse(
@@ -2724,7 +2787,8 @@ var init_ai_check_provider = __esm({
2724
2787
  processedPrompt,
2725
2788
  sessionInfo.parentSessionId,
2726
2789
  schema,
2727
- config.checkName
2790
+ config.checkName,
2791
+ sessionMode
2728
2792
  );
2729
2793
  } else {
2730
2794
  if (aiConfig.debug) {
@@ -5656,9 +5720,11 @@ var init_github_check_service = __esm({
5656
5720
  reviewIssues,
5657
5721
  executionError
5658
5722
  );
5659
- let filteredIssues = reviewIssues;
5723
+ let filteredIssues = reviewIssues.filter(
5724
+ (issue) => !(issue.file === "system" && issue.line === 0)
5725
+ );
5660
5726
  if (filesChangedInCommit && filesChangedInCommit.length > 0) {
5661
- filteredIssues = reviewIssues.filter(
5727
+ filteredIssues = filteredIssues.filter(
5662
5728
  (issue) => filesChangedInCommit.some((changedFile) => issue.file === changedFile)
5663
5729
  );
5664
5730
  }
@@ -7749,6 +7815,12 @@ ${expr}
7749
7815
  `\u{1F527} Debug: Completed check: ${checkName}, issues found: ${(finalResult.issues || []).length}`
7750
7816
  );
7751
7817
  }
7818
+ if (finalResult.sessionId) {
7819
+ sessionIds.set(checkName, finalResult.sessionId);
7820
+ if (debug) {
7821
+ log2(`\u{1F527} Debug: Tracked cloned session for cleanup: ${finalResult.sessionId}`);
7822
+ }
7823
+ }
7752
7824
  }
7753
7825
  const enrichedIssues = (finalResult.issues || []).map((issue) => ({
7754
7826
  ...issue,
@@ -9586,6 +9658,11 @@ var init_config_schema = __esm({
9586
9658
  type: ["string", "boolean"],
9587
9659
  description: "Check name to reuse AI session from, or true to use first dependency (only works with depends_on)"
9588
9660
  },
9661
+ session_mode: {
9662
+ type: "string",
9663
+ enum: ["clone", "append"],
9664
+ description: "How to reuse AI session: 'clone' (default, copy history) or 'append' (share history)"
9665
+ },
9589
9666
  fail_if: {
9590
9667
  type: "string",
9591
9668
  description: "Simple fail condition - fails check if expression evaluates to true"
@@ -11129,6 +11206,22 @@ var ConfigManager = class {
11129
11206
  }
11130
11207
  }
11131
11208
  }
11209
+ if (checkConfig.session_mode !== void 0) {
11210
+ if (checkConfig.session_mode !== "clone" && checkConfig.session_mode !== "append") {
11211
+ errors.push({
11212
+ field: `checks.${checkName}.session_mode`,
11213
+ message: `Invalid session_mode value for "${checkName}": must be 'clone' or 'append'`,
11214
+ value: checkConfig.session_mode
11215
+ });
11216
+ }
11217
+ if (!checkConfig.reuse_ai_session) {
11218
+ errors.push({
11219
+ field: `checks.${checkName}.session_mode`,
11220
+ message: `Check "${checkName}" has session_mode but no reuse_ai_session. session_mode requires reuse_ai_session to be set.`,
11221
+ value: checkConfig.session_mode
11222
+ });
11223
+ }
11224
+ }
11132
11225
  if (checkConfig.tags !== void 0) {
11133
11226
  if (!Array.isArray(checkConfig.tags)) {
11134
11227
  errors.push({