@in-the-loop-labs/pair-review 1.6.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +77 -4
  2. package/package.json +1 -1
  3. package/plugin/.claude-plugin/plugin.json +1 -1
  4. package/plugin/skills/review-requests/SKILL.md +4 -1
  5. package/plugin-code-critic/.claude-plugin/plugin.json +1 -1
  6. package/plugin-code-critic/skills/analyze/SKILL.md +4 -3
  7. package/public/css/pr.css +1930 -114
  8. package/public/js/CONVENTIONS.md +16 -0
  9. package/public/js/components/AIPanel.js +66 -0
  10. package/public/js/components/AnalysisConfigModal.js +2 -2
  11. package/public/js/components/ChatPanel.js +2952 -0
  12. package/public/js/components/CouncilProgressModal.js +12 -16
  13. package/public/js/components/KeyboardShortcuts.js +3 -0
  14. package/public/js/components/PanelGroup.js +723 -0
  15. package/public/js/components/PreviewModal.js +3 -8
  16. package/public/js/index.js +8 -0
  17. package/public/js/local.js +17 -615
  18. package/public/js/modules/analysis-history.js +19 -68
  19. package/public/js/modules/comment-manager.js +57 -19
  20. package/public/js/modules/diff-context.js +176 -0
  21. package/public/js/modules/diff-renderer.js +30 -0
  22. package/public/js/modules/file-comment-manager.js +126 -105
  23. package/public/js/modules/file-list-merger.js +64 -0
  24. package/public/js/modules/panel-resizer.js +25 -6
  25. package/public/js/modules/suggestion-manager.js +40 -125
  26. package/public/js/pr.js +964 -159
  27. package/public/js/repo-settings.js +36 -6
  28. package/public/js/utils/category-emoji.js +44 -0
  29. package/public/js/utils/time.js +32 -0
  30. package/public/local.html +107 -70
  31. package/public/pr.html +107 -70
  32. package/public/repo-settings.html +32 -0
  33. package/src/ai/analyzer.js +5 -1
  34. package/src/ai/copilot-provider.js +39 -9
  35. package/src/ai/cursor-agent-provider.js +36 -7
  36. package/src/ai/gemini-provider.js +17 -4
  37. package/src/ai/prompts/config.js +7 -1
  38. package/src/ai/provider-availability.js +1 -1
  39. package/src/ai/provider.js +25 -37
  40. package/src/chat/CONVENTIONS.md +18 -0
  41. package/src/chat/pi-bridge.js +491 -0
  42. package/src/chat/prompt-builder.js +262 -0
  43. package/src/chat/session-manager.js +619 -0
  44. package/src/config.js +14 -0
  45. package/src/database.js +322 -15
  46. package/src/main.js +4 -17
  47. package/src/routes/analyses.js +721 -0
  48. package/src/routes/chat.js +655 -0
  49. package/src/routes/config.js +29 -8
  50. package/src/routes/context-files.js +223 -0
  51. package/src/routes/local.js +225 -1133
  52. package/src/routes/mcp.js +39 -30
  53. package/src/routes/pr.js +410 -52
  54. package/src/routes/reviews.js +1035 -0
  55. package/src/routes/shared.js +4 -29
  56. package/src/server.js +34 -12
  57. package/src/sse/review-events.js +46 -0
  58. package/src/utils/auto-context.js +88 -0
  59. package/src/utils/category-emoji.js +33 -0
  60. package/src/utils/diff-file-list.js +57 -0
  61. package/src/routes/analysis.js +0 -1600
  62. package/src/routes/comments.js +0 -534
@@ -21,9 +21,6 @@ class CouncilProgressModal {
21
21
 
22
22
  // Track per-voice completion state
23
23
  this._voiceStates = {};
24
- // Track SSE endpoint mode
25
- this._useLocalEndpoint = false;
26
- this._localReviewId = null;
27
24
 
28
25
  this._createModal();
29
26
  this._setupEventListeners();
@@ -131,7 +128,7 @@ class CouncilProgressModal {
131
128
  }
132
129
 
133
130
  try {
134
- await fetch(`/api/analyze/cancel/${this.currentAnalysisId}`, { method: 'POST' });
131
+ await fetch(`/api/analyses/${this.currentAnalysisId}/cancel`, { method: 'POST' });
135
132
  } catch (error) {
136
133
  console.warn('Cancel not available on server:', error.message);
137
134
  }
@@ -148,20 +145,21 @@ class CouncilProgressModal {
148
145
  }
149
146
 
150
147
  /**
151
- * Configure for local mode SSE endpoint.
152
- * @param {string|number} reviewId
148
+ * Configure for local mode.
149
+ * Retained as a public method since callers invoke it, but the SSE endpoint
150
+ * is now unified so no per-mode state is needed.
153
151
  */
154
- setLocalMode(reviewId) {
155
- this._useLocalEndpoint = true;
156
- this._localReviewId = reviewId;
152
+ setLocalMode(_reviewId) {
153
+ // no-op: SSE endpoint is unified
157
154
  }
158
155
 
159
156
  /**
160
- * Configure for PR mode SSE endpoint (default).
157
+ * Configure for PR mode (default).
158
+ * Retained as a public method since callers invoke it, but the SSE endpoint
159
+ * is now unified so no per-mode state is needed.
161
160
  */
162
161
  setPRMode() {
163
- this._useLocalEndpoint = false;
164
- this._localReviewId = null;
162
+ // no-op: SSE endpoint is unified
165
163
  }
166
164
 
167
165
  // ---------------------------------------------------------------------------
@@ -174,9 +172,7 @@ class CouncilProgressModal {
174
172
  }
175
173
  if (!this.currentAnalysisId) return;
176
174
 
177
- const sseUrl = this._useLocalEndpoint
178
- ? `/api/local/${this._localReviewId}/ai-suggestions/status`
179
- : `/api/pr/${this.currentAnalysisId}/ai-suggestions/status`;
175
+ const sseUrl = `/api/analyses/${this.currentAnalysisId}/progress`;
180
176
 
181
177
  this.eventSource = new EventSource(sseUrl);
182
178
 
@@ -228,7 +224,7 @@ class CouncilProgressModal {
228
224
  this.statusCheckInterval = setInterval(async () => {
229
225
  if (!this.currentAnalysisId) return;
230
226
  try {
231
- const response = await fetch(`/api/analyze/status/${this.currentAnalysisId}`);
227
+ const response = await fetch(`/api/analyses/${this.currentAnalysisId}/status`);
232
228
  if (!response.ok) throw new Error('Failed to fetch status');
233
229
  const status = await response.json();
234
230
  this.updateProgress(status);
@@ -142,6 +142,7 @@ class KeyboardShortcuts {
142
142
  const groups = {
143
143
  navigation: { title: 'Navigation', shortcuts: [] },
144
144
  comments: { title: 'Comments', shortcuts: [] },
145
+ panels: { title: 'Panels', shortcuts: [] },
145
146
  general: { title: 'General', shortcuts: [] }
146
147
  };
147
148
 
@@ -154,6 +155,8 @@ class KeyboardShortcuts {
154
155
  groups.navigation.shortcuts.push(item);
155
156
  } else if (keys[0] === 'c') {
156
157
  groups.comments.shortcuts.push(item);
158
+ } else if (keys[0] === 'p') {
159
+ groups.panels.shortcuts.push(item);
157
160
  } else {
158
161
  groups.general.shortcuts.push(item);
159
162
  }