Copilot Continue

Auto-clicks the "Continue" button when GitHub Copilot gets stuck

  1. // ==UserScript==
  2. // @name Copilot Continue
  3. // @namespace https://snomiao.com
  4. // @match *://*/*
  5. // @grant none
  6. // @version 1.1.1
  7. // @author snomiao
  8. // @description Auto-clicks the "Continue" button when GitHub Copilot gets stuck
  9. // @homepage https://github.com/snomiao/copilot-continue.user.js
  10. // @supportURL https://github.com/snomiao/copilot-continue.user.js/issues
  11. // @license MIT
  12. // @compatible chrome
  13. // @compatible firefox
  14. // @compatible edge
  15. // @compatible opera
  16. // ==/UserScript==
  17.  
  18. // webhook...update = fetch(globalThis.GM_info.script.downloadURL)
  19.  
  20. /*
  21. * Copilot Continue - A userscript to automatically continue GitHub Copilot
  22. *
  23. * This script automatically clicks the "Continue" button when GitHub Copilot
  24. * shows interruption messages like:
  25. * - "Copilot has been working on this problem for a while"
  26. * - "Run command in the terminal"
  27. * - "Allow task run?"
  28. *
  29. * The script runs in VS Code web environments and checks for interruptions every second.
  30. */
  31.  
  32. const enable = !!document.querySelector("meta#vscode-workbench-auth-session");
  33.  
  34. if (enable) main()
  35.  
  36. function main() {
  37. const clear = useInterval(() => clicks(), 1e3);
  38. return () => clear();
  39. }
  40. function clicks(){
  41. clickTryAgain() || clickContinue()
  42. }
  43.  
  44. function clickTryAgain(){
  45. const stucked = $$("div.rendered-markdown")
  46. .map((e) => e.innerText)
  47. .flatMap((e) => (e ? [e] : [])) // empty filter
  48. .map(e=>e.replace(/\s+/g,' '))
  49. .findLast(s=> false||
  50. s.match("The model unexpectedly did not return a response, which may indicate a service issue. Please report a bug.")
  51. );
  52. if(!stucked) return;
  53.  
  54. //
  55. // const btn = $$("a.monaco-button").findLast(
  56. // (e) => e.textContent === "Try Again"
  57. // );
  58. // if (!btn) return;
  59. // btn.click();
  60.  
  61. // Seems not working by click try again
  62. // So reload page when try again.
  63. location.href = location.href
  64.  
  65. return true;
  66. }
  67.  
  68. function clickContinue() {
  69. const stucked = $$("div.rendered-markdown")
  70. .map((e) => e.innerText)
  71. .flatMap((e) => (e ? [e] : [])) // empty filter
  72. .map(e=>e.replace(/\s+/g,' '))
  73. .findLast(
  74. (s) =>
  75. false ||
  76. s.match(/Copilot has been working on this problem for a while/) ||
  77. s.match(/Run command in terminal/) ||
  78. s.match(/Continue to iterate\?/) ||
  79. s.match(/Allow task run\?/)
  80. );
  81. if (!stucked) return;
  82. const btn = $$("a.monaco-button").findLast(
  83. (e) => e.textContent === "Continue"
  84. );
  85. if (!btn) return;
  86. btn.click();
  87. return true;
  88. }
  89.  
  90. function $$(sel) {
  91. return [...document.querySelectorAll(sel)];
  92. }
  93.  
  94. function useInterval(...args) {
  95. const id = setInterval(...args);
  96. return () => clearInterval(id);
  97. }