@in-the-loop-labs/pair-review 3.9.1 → 4.1.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 (53) hide show
  1. package/README.md +92 -17
  2. package/package.json +6 -9
  3. package/plugin/.claude-plugin/plugin.json +1 -1
  4. package/plugin-code-critic/.claude-plugin/plugin.json +3 -4
  5. package/plugin-pair-loop/.claude-plugin/plugin.json +19 -0
  6. package/plugin-pair-loop/skills/loop/SKILL.md +233 -0
  7. package/public/js/components/AdvancedConfigTab.js +1 -1
  8. package/public/js/components/AnalysisConfigModal.js +2 -2
  9. package/public/js/index.js +87 -10
  10. package/public/js/local.js +20 -10
  11. package/public/js/pr.js +67 -39
  12. package/public/js/repo-links.js +11 -3
  13. package/public/js/utils/analyze-params.js +69 -0
  14. package/public/js/utils/provider-model.js +67 -2
  15. package/public/js/vendor/pierre-diffs-worker.js +16158 -0
  16. package/public/js/vendor/pierre-diffs.js +1880 -0
  17. package/public/local.html +1 -0
  18. package/public/pr.html +1 -0
  19. package/public/setup.html +35 -16
  20. package/src/ai/analyzer.js +4 -4
  21. package/src/ai/antigravity-provider.js +594 -0
  22. package/src/ai/index.js +1 -1
  23. package/src/ai/opencode-provider.js +1 -1
  24. package/src/ai/provider.js +5 -5
  25. package/src/ai/stream-parser.js +1 -52
  26. package/src/chat/acp-bridge.js +1 -1
  27. package/src/chat/chat-providers.js +1 -9
  28. package/src/config.js +153 -31
  29. package/src/database.js +128 -4
  30. package/src/external/github-adapter.js +18 -3
  31. package/src/github/client.js +37 -0
  32. package/src/github/parser.js +41 -7
  33. package/src/interactive-analysis-config.js +2 -2
  34. package/src/links/repo-links.js +66 -28
  35. package/src/local-review.js +134 -5
  36. package/src/local-scope.js +38 -0
  37. package/src/main.js +203 -37
  38. package/src/routes/config.js +49 -14
  39. package/src/routes/external-comments.js +13 -1
  40. package/src/routes/github-collections.js +175 -13
  41. package/src/routes/local.js +11 -20
  42. package/src/routes/pr.js +63 -36
  43. package/src/routes/setup.js +63 -8
  44. package/src/routes/shared.js +85 -0
  45. package/src/routes/stack-analysis.js +39 -3
  46. package/src/server.js +74 -3
  47. package/src/setup/local-setup.js +23 -7
  48. package/src/setup/pr-setup.js +237 -39
  49. package/src/setup/stack-setup.js +7 -2
  50. package/src/single-port.js +73 -18
  51. package/src/utils/host-resolution.js +157 -0
  52. package/plugin-code-critic/skills/loop/SKILL.md +0 -373
  53. package/src/ai/gemini-provider.js +0 -752
package/public/local.html CHANGED
@@ -591,6 +591,7 @@
591
591
  <!-- Shared storage-key and provider/model helpers -->
592
592
  <script src="/js/utils/storage-keys.js"></script>
593
593
  <script src="/js/utils/provider-model.js"></script>
594
+ <script src="/js/utils/analyze-params.js"></script>
594
595
 
595
596
  <!-- Category emoji mapping -->
596
597
  <script src="/js/utils/category-emoji.js"></script>
package/public/pr.html CHANGED
@@ -394,6 +394,7 @@
394
394
  <!-- Shared storage-key and provider/model helpers -->
395
395
  <script src="/js/utils/storage-keys.js"></script>
396
396
  <script src="/js/utils/provider-model.js"></script>
397
+ <script src="/js/utils/analyze-params.js"></script>
397
398
 
398
399
  <!-- Category emoji mapping -->
399
400
  <script src="/js/utils/category-emoji.js"></script>
package/public/setup.html CHANGED
@@ -530,6 +530,7 @@
530
530
  <script src="/js/ws-client.js"></script>
531
531
  <script src="/js/components/UpdateBanner.js"></script>
532
532
  <script src="/js/utils/notification-sounds.js"></script>
533
+ <script src="/js/utils/analyze-params.js"></script>
533
534
 
534
535
  <script>
535
536
  // Copyright 2026 Tim Perkins (tjwp) | SPDX-License-Identifier: Apache-2.0
@@ -611,6 +612,14 @@
611
612
  context.path = params.get('path');
612
613
  }
613
614
  }
615
+ // Forward a delegated --scope/--base selection (the CLI carries them
616
+ // on the /local?path=... URL when delegating to a running server).
617
+ // The server re-validates; this only relays the request.
618
+ if (mode === 'local') {
619
+ const scopeParams = new URLSearchParams(window.location.search);
620
+ if (scopeParams.get('scope')) context.scope = scopeParams.get('scope');
621
+ if (scopeParams.get('base')) context.base = scopeParams.get('base');
622
+ }
614
623
 
615
624
  const steps = mode === 'local' ? LOCAL_STEPS : PR_STEPS;
616
625
  const stepStates = {};
@@ -751,7 +760,23 @@
751
760
  var fetchOptions = { method: 'POST' };
752
761
  if (mode === 'local') {
753
762
  fetchOptions.headers = { 'Content-Type': 'application/json' };
754
- fetchOptions.body = JSON.stringify({ path: context.path });
763
+ var localBody = { path: context.path };
764
+ if (context.scope) localBody.scope = context.scope;
765
+ if (context.base) localBody.base = context.base;
766
+ fetchOptions.body = JSON.stringify(localBody);
767
+ } else if (mode === 'pr') {
768
+ // A `host` query param (set when opening a PR from a dashboard
769
+ // collection row or a pasted URL) tells setup which system the
770
+ // PR lives on, so the fetch binds there directly instead of
771
+ // probing. Sentinel: the literal "github" means github.com and
772
+ // maps to body host null; any other value is an api_host URL
773
+ // string (alt host) — an api_host is always a URL, so "github"
774
+ // is unambiguous. Absent = unknown; the server derives the host.
775
+ var setupHost = new URLSearchParams(window.location.search).get('host');
776
+ if (setupHost) {
777
+ fetchOptions.headers = { 'Content-Type': 'application/json' };
778
+ fetchOptions.body = JSON.stringify({ host: setupHost === 'github' ? null : setupHost });
779
+ }
755
780
  }
756
781
 
757
782
  var response = await fetch(postUrl, fetchOptions);
@@ -764,16 +789,13 @@
764
789
 
765
790
  var data = await response.json();
766
791
 
767
- // If the review already exists, redirect immediately
792
+ // If the review already exists, redirect immediately.
793
+ // Relay the full auto-analyze intent bundle (analyze /
794
+ // analysisConfigId / council / provider / model) so a delegated
795
+ // override or CLI council survives this hop to the review page.
768
796
  if (data.existing && data.reviewUrl) {
769
797
  var targetUrl = new URL(data.reviewUrl, window.location.origin);
770
- var qs = new URLSearchParams(window.location.search);
771
- if (qs.get('analyze') === 'true') targetUrl.searchParams.set('analyze', qs.get('analyze'));
772
- if (qs.get('analysisConfigId')) targetUrl.searchParams.set('analysisConfigId', qs.get('analysisConfigId'));
773
- // Forward the CLI-supplied council selection (PR & local cold-start
774
- // and delegated paths route through here); the review page keys
775
- // council auto-analysis on this param.
776
- if (qs.get('council')) targetUrl.searchParams.set('council', qs.get('council'));
798
+ window.carryAnalyzeParams(window.location.search, targetUrl);
777
799
  window.location.href = targetUrl.toString();
778
800
  return;
779
801
  }
@@ -832,13 +854,10 @@
832
854
  setTimeout(function() {
833
855
  if (msg.reviewUrl) {
834
856
  var targetUrl = new URL(msg.reviewUrl, window.location.origin);
835
- var qs = new URLSearchParams(window.location.search);
836
- if (qs.get('analyze') === 'true') targetUrl.searchParams.set('analyze', qs.get('analyze'));
837
- if (qs.get('analysisConfigId')) targetUrl.searchParams.set('analysisConfigId', qs.get('analysisConfigId'));
838
- // Forward the CLI-supplied council selection (PR & local cold-start
839
- // and delegated paths route through here); the review page keys
840
- // council auto-analysis on this param.
841
- if (qs.get('council')) targetUrl.searchParams.set('council', qs.get('council'));
857
+ // Relay the full auto-analyze intent bundle (analyze /
858
+ // analysisConfigId / council / provider / model) so a
859
+ // delegated override or CLI council survives the hop.
860
+ window.carryAnalyzeParams(window.location.search, targetUrl);
842
861
  window.location.href = targetUrl.toString();
843
862
  }
844
863
  }, 400);
@@ -342,8 +342,8 @@ A suggestion is a duplicate if it targets the same file and overlapping lines an
342
342
  class Analyzer {
343
343
  /**
344
344
  * @param {Object} database - Database instance
345
- * @param {string} model - Model to use (e.g., 'opus', 'gemini-2.5-pro')
346
- * @param {string} provider - Provider ID (e.g., 'claude', 'gemini'). Defaults to 'claude'.
345
+ * @param {string} model - Model to use (e.g., 'opus', 'gemini-3.1-pro-low')
346
+ * @param {string} provider - Provider ID (e.g., 'claude', 'antigravity'). Defaults to 'claude'.
347
347
  * @param {Object} providerOverrides - Per-call config overrides passed to createProvider (optional)
348
348
  * @param {Object|null} providerOverridesMap - Per-provider overrides map for council mode (provider ID → overrides)
349
349
  */
@@ -860,8 +860,8 @@ class Analyzer {
860
860
  *
861
861
  * Uses the bare command name since BIN_DIR is added to PATH in all
862
862
  * providers. Using the absolute path causes issues with AI providers
863
- * that pattern-match allowed tools (e.g., Gemini only matches
864
- * 'git-diff-lines', not the full path).
863
+ * that pattern-match allowed shell commands by their bare command name
864
+ * (matching 'git-diff-lines', not the full path).
865
865
  *
866
866
  * @param {string|null} worktreePath - Path to the git worktree
867
867
  * @returns {string} e.g. `git-diff-lines` or `git-diff-lines --cwd "/path"`