@profoundlogic/coderflow-server 0.2.1

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 (202) hide show
  1. package/LICENSE.txt +322 -0
  2. package/README.md +158 -0
  3. package/dist/LICENSE.txt +322 -0
  4. package/dist/README.md +158 -0
  5. package/dist/base-image/Dockerfile +184 -0
  6. package/dist/base-image/agent-wrapper.sh +143 -0
  7. package/dist/base-image/apply-local-state.sh +357 -0
  8. package/dist/base-image/coder-git-credential-helper +307 -0
  9. package/dist/base-image/entrypoint.sh +942 -0
  10. package/dist/base-image/ssh_config_template +41 -0
  11. package/dist/base-image/start-code-server.sh +76 -0
  12. package/dist/base-image/sync-repos.sh +170 -0
  13. package/dist/base-image/vscode-extensions.txt +10 -0
  14. package/dist/base-image/vscode-settings.json +41 -0
  15. package/dist/coder-server.js +2 -0
  16. package/dist/config/cli-models.json +45 -0
  17. package/dist/config/imported-skills.schema.json +83 -0
  18. package/dist/config/skill-catalog.json +18 -0
  19. package/dist/config/skill-catalog.schema.json +140 -0
  20. package/dist/config.js +1 -0
  21. package/dist/examples/oidc.json.example +11 -0
  22. package/dist/lib/agent-keepalive.js +1 -0
  23. package/dist/lib/api-keys.js +1 -0
  24. package/dist/lib/apiKeys.js +1 -0
  25. package/dist/lib/auto-judge.js +1 -0
  26. package/dist/lib/basic-auth.js +1 -0
  27. package/dist/lib/build-history.js +1 -0
  28. package/dist/lib/build-output-service.js +1 -0
  29. package/dist/lib/build-scheduler.js +1 -0
  30. package/dist/lib/build-service.js +1 -0
  31. package/dist/lib/claude-oauth-refresh.js +1 -0
  32. package/dist/lib/cli/build.js +1 -0
  33. package/dist/lib/cli/config-command.js +1 -0
  34. package/dist/lib/cli/config.js +1 -0
  35. package/dist/lib/cli/create-user.js +1 -0
  36. package/dist/lib/cli/init.js +1 -0
  37. package/dist/lib/cli/jira.js +1 -0
  38. package/dist/lib/cli/license.js +1 -0
  39. package/dist/lib/cli/server-manager.js +1 -0
  40. package/dist/lib/container-tokens.js +1 -0
  41. package/dist/lib/data-dir.js +1 -0
  42. package/dist/lib/deployment-history.js +1 -0
  43. package/dist/lib/deployment-service.js +1 -0
  44. package/dist/lib/docker-utils.js +1 -0
  45. package/dist/lib/email.js +1 -0
  46. package/dist/lib/emailTemplates.js +1 -0
  47. package/dist/lib/entitlement.js +1 -0
  48. package/dist/lib/fetch-utils.js +1 -0
  49. package/dist/lib/git-provider-service.js +1 -0
  50. package/dist/lib/git-provider-setup/assets/coderflow_github_app.png +0 -0
  51. package/dist/lib/git-provider-setup/github-setup-handler.js +1 -0
  52. package/dist/lib/git-provider-setup/index.js +1 -0
  53. package/dist/lib/git-provider-setup/setup-factory.js +1 -0
  54. package/dist/lib/git-provider-setup/setup-interface.js +1 -0
  55. package/dist/lib/git-providers/azure-devops-provider.js +1 -0
  56. package/dist/lib/git-providers/github-app-provider.js +1 -0
  57. package/dist/lib/git-providers/index.js +1 -0
  58. package/dist/lib/git-providers/provider-factory.js +1 -0
  59. package/dist/lib/git-providers/provider-interface.js +1 -0
  60. package/dist/lib/jira-client.js +1 -0
  61. package/dist/lib/logger.js +1 -0
  62. package/dist/lib/model-fetcher.js +1 -0
  63. package/dist/lib/notifications.js +1 -0
  64. package/dist/lib/oidc-auth.js +1 -0
  65. package/dist/lib/oidc-device-flow.js +1 -0
  66. package/dist/lib/passwordTokens.js +1 -0
  67. package/dist/lib/pin-cascade.js +1 -0
  68. package/dist/lib/provider-accounts.js +1 -0
  69. package/dist/lib/provider-oauth.js +1 -0
  70. package/dist/lib/provider-profile.js +1 -0
  71. package/dist/lib/provider-token-refresh.js +1 -0
  72. package/dist/lib/roles.js +1 -0
  73. package/dist/lib/secrets.js +1 -0
  74. package/dist/lib/state-capture.js +1 -0
  75. package/dist/lib/static-files.js +1 -0
  76. package/dist/lib/task-name-generator.js +1 -0
  77. package/dist/lib/users.js +1 -0
  78. package/dist/middleware/requireAuth.js +1 -0
  79. package/dist/middleware/requireInit.js +1 -0
  80. package/dist/middleware/requirePermission.js +1 -0
  81. package/dist/package-lock.json +4151 -0
  82. package/dist/package.json +50 -0
  83. package/dist/routes/apiKeys.js +1 -0
  84. package/dist/routes/auth-oidc.js +1 -0
  85. package/dist/routes/auth.js +1 -0
  86. package/dist/routes/build.js +1 -0
  87. package/dist/routes/containers.js +1 -0
  88. package/dist/routes/deploy-task.js +1 -0
  89. package/dist/routes/environment-management.js +1 -0
  90. package/dist/routes/environments.js +1 -0
  91. package/dist/routes/external-skills.js +1 -0
  92. package/dist/routes/git-credentials.js +1 -0
  93. package/dist/routes/git-provider-setup.js +1 -0
  94. package/dist/routes/health.js +1 -0
  95. package/dist/routes/jira.js +1 -0
  96. package/dist/routes/objective-management.js +1 -0
  97. package/dist/routes/password.js +1 -0
  98. package/dist/routes/prompt.js +1 -0
  99. package/dist/routes/provider-auth.js +1 -0
  100. package/dist/routes/qa.js +1 -0
  101. package/dist/routes/settings.js +1 -0
  102. package/dist/routes/skill-management.js +1 -0
  103. package/dist/routes/skills.js +1 -0
  104. package/dist/routes/tasks.js +2 -0
  105. package/dist/routes/templates.js +1 -0
  106. package/dist/routes/test-task.js +1 -0
  107. package/dist/routes/test.js +1 -0
  108. package/dist/routes/users.js +1 -0
  109. package/dist/routes/visualizations.js +1 -0
  110. package/dist/schemas/template-metadata.schema.json +178 -0
  111. package/dist/scripts/create-user.js +2 -0
  112. package/dist/shipped-skills/environment-instructions/SKILL.md +154 -0
  113. package/dist/shipped-skills/environment-templates/SKILL.md +282 -0
  114. package/dist/shipped-skills/objective-management/SKILL.md +238 -0
  115. package/dist/shipped-skills/skill-editor/SKILL.md +326 -0
  116. package/dist/start.js +2 -0
  117. package/dist/web-ui/public/activity-detail-modal.js +1 -0
  118. package/dist/web-ui/public/activity-feed.js +1 -0
  119. package/dist/web-ui/public/activity-formatters.js +1 -0
  120. package/dist/web-ui/public/agent-event-parser.js +1 -0
  121. package/dist/web-ui/public/app.js +1 -0
  122. package/dist/web-ui/public/approve-dialog.js +1 -0
  123. package/dist/web-ui/public/coderflow-logo-reversed.svg +46 -0
  124. package/dist/web-ui/public/coderflow-logo.svg +46 -0
  125. package/dist/web-ui/public/comments-widget.js +1 -0
  126. package/dist/web-ui/public/docs/.nojekyll +0 -0
  127. package/dist/web-ui/public/docs/README.md +26 -0
  128. package/dist/web-ui/public/docs/_sidebar.md +47 -0
  129. package/dist/web-ui/public/docs/admin/ai-providers.md +132 -0
  130. package/dist/web-ui/public/docs/admin/email-notifications.md +69 -0
  131. package/dist/web-ui/public/docs/admin/environments.md +215 -0
  132. package/dist/web-ui/public/docs/admin/git-providers.md +147 -0
  133. package/dist/web-ui/public/docs/admin/installation.md +313 -0
  134. package/dist/web-ui/public/docs/admin/skills.md +35 -0
  135. package/dist/web-ui/public/docs/admin/sso.md +241 -0
  136. package/dist/web-ui/public/docs/admin/users-and-roles.md +57 -0
  137. package/dist/web-ui/public/docs/code/cli.md +102 -0
  138. package/dist/web-ui/public/docs/code/files-and-editing.md +86 -0
  139. package/dist/web-ui/public/docs/code/terminal-access.md +110 -0
  140. package/dist/web-ui/public/docs/code/vscode-extension.md +58 -0
  141. package/dist/web-ui/public/docs/getting-started/core-concepts.md +129 -0
  142. package/dist/web-ui/public/docs/getting-started/overview.md +46 -0
  143. package/dist/web-ui/public/docs/index.html +151 -0
  144. package/dist/web-ui/public/docs/integrations/custom.md +58 -0
  145. package/dist/web-ui/public/docs/integrations/ibmi/overview.md +58 -0
  146. package/dist/web-ui/public/docs/integrations/overview.md +48 -0
  147. package/dist/web-ui/public/docs/objectives/qa-mode.md +90 -0
  148. package/dist/web-ui/public/docs/objectives/staged-tasks.md +60 -0
  149. package/dist/web-ui/public/docs/objectives/working-with-objectives.md +102 -0
  150. package/dist/web-ui/public/docs/tasks/approval-and-deployment.md +83 -0
  151. package/dist/web-ui/public/docs/tasks/creating-tasks.md +111 -0
  152. package/dist/web-ui/public/docs/tasks/judging.md +114 -0
  153. package/dist/web-ui/public/docs/tasks/providing-feedback.md +41 -0
  154. package/dist/web-ui/public/docs/tasks/task-groups.md +73 -0
  155. package/dist/web-ui/public/docs/tasks/winner-selection.md +75 -0
  156. package/dist/web-ui/public/docs/templates/batch-processing.md +152 -0
  157. package/dist/web-ui/public/docs/templates/task-templates.md +44 -0
  158. package/dist/web-ui/public/docs/templates/template-examples.md +93 -0
  159. package/dist/web-ui/public/docs/testing/profound-automated-testing.md +77 -0
  160. package/dist/web-ui/public/docs/testing/task-visualizations.md +42 -0
  161. package/dist/web-ui/public/docs/testing/testing-menu.md +118 -0
  162. package/dist/web-ui/public/environments.css +3942 -0
  163. package/dist/web-ui/public/environments.html +1791 -0
  164. package/dist/web-ui/public/environments.js +1 -0
  165. package/dist/web-ui/public/favicon-16.png +0 -0
  166. package/dist/web-ui/public/favicon-32.png +0 -0
  167. package/dist/web-ui/public/favicon.ico +0 -0
  168. package/dist/web-ui/public/feedback-widget.css +3133 -0
  169. package/dist/web-ui/public/feedback-widget.js +1 -0
  170. package/dist/web-ui/public/git-history.css +2663 -0
  171. package/dist/web-ui/public/git-history.html +272 -0
  172. package/dist/web-ui/public/git-history.js +1 -0
  173. package/dist/web-ui/public/git-status.js +1 -0
  174. package/dist/web-ui/public/index.html +1459 -0
  175. package/dist/web-ui/public/index.js +1 -0
  176. package/dist/web-ui/public/login.html +346 -0
  177. package/dist/web-ui/public/login.js +1 -0
  178. package/dist/web-ui/public/markdown-editor.js +1 -0
  179. package/dist/web-ui/public/markdown-file-editor.js +1 -0
  180. package/dist/web-ui/public/modal-maximize.js +1 -0
  181. package/dist/web-ui/public/notifications.js +1 -0
  182. package/dist/web-ui/public/server-health.js +1 -0
  183. package/dist/web-ui/public/settings.css +761 -0
  184. package/dist/web-ui/public/settings.html +1044 -0
  185. package/dist/web-ui/public/settings.js +1 -0
  186. package/dist/web-ui/public/setup-password.html +355 -0
  187. package/dist/web-ui/public/setup-password.js +1 -0
  188. package/dist/web-ui/public/skills.css +1949 -0
  189. package/dist/web-ui/public/skills.html +820 -0
  190. package/dist/web-ui/public/skills.js +1 -0
  191. package/dist/web-ui/public/sse-client.js +1 -0
  192. package/dist/web-ui/public/sse-shared-worker.js +1 -0
  193. package/dist/web-ui/public/styles.css +18614 -0
  194. package/dist/web-ui/public/task.html +1779 -0
  195. package/dist/web-ui/public/task.js +1 -0
  196. package/dist/web-ui/public/terminal.html +45 -0
  197. package/dist/web-ui/public/terminal.js +1 -0
  198. package/dist/web-ui/public/theme.js +1 -0
  199. package/dist/web-ui/public/users.html +298 -0
  200. package/dist/web-ui/public/users.js +1 -0
  201. package/dist/web-ui/public/variant-grouping.js +1 -0
  202. package/package.json +63 -0
@@ -0,0 +1,1044 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Server Settings - CoderFlow</title>
7
+ <link rel="icon" href="/favicon.svg" type="image/svg+xml">
8
+ <link rel="icon" href="/favicon-32.png" type="image/png" sizes="32x32">
9
+ <link rel="icon" href="/favicon-16.png" type="image/png" sizes="16x16">
10
+ <link rel="icon" href="/favicon.ico">
11
+ <script>
12
+ (() => {
13
+ const key = 'profound-coder-theme';
14
+ try {
15
+ const stored = localStorage.getItem(key);
16
+ const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
17
+ const theme = stored === 'dark' || stored === 'light' ? stored : (prefersDark ? 'dark' : 'light');
18
+ document.documentElement.dataset.theme = theme;
19
+ document.documentElement.style.colorScheme = theme === 'dark' ? 'dark' : 'light';
20
+ } catch (error) {
21
+ document.documentElement.dataset.theme = 'light';
22
+ }
23
+ })();
24
+ </script>
25
+ <link rel="stylesheet" href="styles.css?v=84">
26
+ <link rel="stylesheet" href="settings.css?v=1">
27
+ <script type="module" src="app.js?v=67"></script>
28
+ <script type="module" src="settings.js?v=1"></script>
29
+ </head>
30
+ <body>
31
+ <main class="task-detail">
32
+ <div class="task-hero">
33
+ <div class="hero-top">
34
+ <nav class="breadcrumb" aria-label="Breadcrumb">
35
+ <a class="breadcrumb-link" href="index.html">
36
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
37
+ <path d="M3 11.5L12 4l9 7.5"></path>
38
+ <path d="M5 10.5V20h5v-5h4v5h5v-9.5"></path>
39
+ </svg>
40
+ <span>Home</span>
41
+ </a>
42
+ <span class="breadcrumb-separator" aria-hidden="true">/</span>
43
+ <span class="breadcrumb-current">Settings</span>
44
+ </nav>
45
+ <span class="task-context">Administration</span>
46
+ <!-- Admin Menu (gear icon) -->
47
+ <div class="admin-menu-container" id="admin-menu-container" hidden>
48
+ <button class="btn-icon-admin" id="admin-menu-btn" title="Admin">
49
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
50
+ <circle cx="12" cy="12" r="3"></circle>
51
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
52
+ </svg>
53
+ </button>
54
+ <div class="dropdown-menu admin-dropdown" id="admin-menu" hidden>
55
+ <button type="button" class="dropdown-item admin-menu-item" onclick="window.location.href='users.html'">
56
+ <svg class="option-icon icon-users" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
57
+ <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
58
+ <circle cx="9" cy="7" r="4"></circle>
59
+ <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
60
+ <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
61
+ </svg>
62
+ <span class="option-text">Users</span>
63
+ </button>
64
+ <button type="button" class="dropdown-item admin-menu-item" onclick="window.location.href='environments.html'">
65
+ <svg class="option-icon icon-environments" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
66
+ <circle cx="12" cy="12" r="10"></circle>
67
+ <line x1="2" y1="12" x2="22" y2="12"></line>
68
+ <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
69
+ </svg>
70
+ <span class="option-text">Environments</span>
71
+ </button>
72
+ <button type="button" class="dropdown-item admin-menu-item" onclick="window.location.href='skills.html'">
73
+ <svg class="option-icon icon-skills" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
74
+ <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path>
75
+ </svg>
76
+ <span class="option-text">Skills</span>
77
+ </button>
78
+ <button type="button" class="dropdown-item admin-menu-item" id="server-health-btn">
79
+ <svg class="option-icon icon-health" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
80
+ <path d="M22 12h-4l-3 9L9 3l-3 9H2"></path>
81
+ </svg>
82
+ <span class="option-text">Server Health</span>
83
+ </button>
84
+ <button type="button" class="dropdown-item admin-menu-item" onclick="window.location.href='git-history.html'">
85
+ <svg class="option-icon icon-git-history" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
86
+ <circle cx="6" cy="6" r="2"></circle>
87
+ <circle cx="6" cy="18" r="2"></circle>
88
+ <circle cx="18" cy="12" r="2"></circle>
89
+ <path d="M6 8v8"></path>
90
+ <path d="M6 12h10"></path>
91
+ </svg>
92
+ <span class="option-text">Git History</span>
93
+ </button>
94
+ </div>
95
+ </div>
96
+ <div id="theme-toggle-container"></div>
97
+ </div>
98
+ <div class="status-hero">
99
+ <div class="status-copy">
100
+ <h1>Server Settings</h1>
101
+ <p class="task-subtitle">Configure global server settings and integrations</p>
102
+ </div>
103
+ </div>
104
+ </div>
105
+
106
+ <!-- Loading State -->
107
+ <div id="settings-loading" class="loading">
108
+ <svg class="loading-spinner" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
109
+ <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
110
+ </svg>
111
+ <span>Loading settings...</span>
112
+ </div>
113
+
114
+ <!-- Error State -->
115
+ <div id="settings-error" class="empty-state-card" hidden>
116
+ <div class="empty-state-icon">⚠️</div>
117
+ <h2>Failed to load settings</h2>
118
+ <p id="settings-error-message" class="text-muted"></p>
119
+ <button class="btn-primary" id="retry-settings-btn">Try Again</button>
120
+ </div>
121
+
122
+ <!-- Main Content -->
123
+ <div id="settings-content" class="settings-layout" hidden>
124
+ <!-- Settings Navigation -->
125
+ <aside class="settings-sidebar">
126
+ <nav class="settings-nav" role="tablist">
127
+ <button class="settings-nav-item active" data-section="general" role="tab">
128
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
129
+ <path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"></path>
130
+ <circle cx="12" cy="12" r="3"></circle>
131
+ </svg>
132
+ General
133
+ </button>
134
+ <button class="settings-nav-item" data-section="keepalive" role="tab">
135
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
136
+ <path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"></path>
137
+ <path d="M21 3v5h-5"></path>
138
+ </svg>
139
+ Agent Keepalive
140
+ </button>
141
+ <button class="settings-nav-item" data-section="apikeys" role="tab">
142
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
143
+ <path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path>
144
+ </svg>
145
+ API Keys
146
+ </button>
147
+ <button class="settings-nav-item" data-section="provider-auth" role="tab">
148
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
149
+ <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
150
+ <polyline points="10 17 15 12 10 7"></polyline>
151
+ <line x1="15" y1="12" x2="3" y2="12"></line>
152
+ </svg>
153
+ Provider Authentication
154
+ </button>
155
+ <button class="settings-nav-item" data-section="models" role="tab">
156
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
157
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
158
+ <line x1="3" y1="9" x2="21" y2="9"></line>
159
+ <line x1="9" y1="21" x2="9" y2="9"></line>
160
+ </svg>
161
+ Model Configuration
162
+ </button>
163
+ <button class="settings-nav-item" data-section="email" role="tab">
164
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
165
+ <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
166
+ <polyline points="22,6 12,13 2,6"></polyline>
167
+ </svg>
168
+ Email (SMTP)
169
+ </button>
170
+ <button class="settings-nav-item" data-section="git-providers" role="tab">
171
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
172
+ <path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
173
+ </svg>
174
+ Git Providers
175
+ </button>
176
+ <button class="settings-nav-item" data-section="sso" role="tab">
177
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
178
+ <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
179
+ <path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
180
+ </svg>
181
+ Single Sign-On
182
+ </button>
183
+ </nav>
184
+ </aside>
185
+
186
+ <!-- Settings Panels -->
187
+ <section class="settings-panels">
188
+ <!-- General Settings -->
189
+ <div id="section-general" class="settings-panel active" role="tabpanel">
190
+ <div class="content-card">
191
+ <div class="card-header">
192
+ <h3>General Settings</h3>
193
+ </div>
194
+ <div class="card-body">
195
+ <div id="general-inline-message" class="inline-message" hidden></div>
196
+ <div class="form-single-column">
197
+ <div class="form-row">
198
+ <label for="settings-name">Setup Name</label>
199
+ <input type="text" id="settings-name" class="form-input" placeholder="e.g., my-coder-setup">
200
+ </div>
201
+ <div class="form-row">
202
+ <label for="settings-default-agent">Default Agent</label>
203
+ <div id="settings-default-agent-container"></div>
204
+ </div>
205
+ <div class="form-row">
206
+ <label for="settings-default-environment">Default Environment</label>
207
+ <div id="settings-default-environment-container"></div>
208
+ </div>
209
+ <div class="form-row">
210
+ <label for="settings-max-concurrent-agents">Max Concurrent Agents</label>
211
+ <input type="number" id="settings-max-concurrent-agents" class="form-input" min="1" max="100" value="8" style="max-width: 120px;">
212
+ <span class="form-hint">Limit how many agents can run simultaneously (tasks exceeding this limit will be queued)</span>
213
+ </div>
214
+ </div>
215
+ </div>
216
+ <div class="card-actions">
217
+ <button type="button" class="btn-primary" id="save-general-btn">Save</button>
218
+ </div>
219
+ </div>
220
+ </div>
221
+
222
+ <!-- Agent Keepalive Settings -->
223
+ <div id="section-keepalive" class="settings-panel" role="tabpanel" hidden>
224
+ <div class="content-card">
225
+ <div class="card-header">
226
+ <h3>Agent Keepalive Settings</h3>
227
+ </div>
228
+ <div class="card-body">
229
+ <div id="keepalive-inline-message" class="inline-message" hidden></div>
230
+ <p class="text-muted" style="margin-bottom: 20px;">Configure automatic token refresh for each agent to keep them authenticated and responsive</p>
231
+
232
+ <div id="keepalive-agents-container">
233
+ <!-- Claude -->
234
+ <div class="keepalive-agent-section">
235
+ <div class="keepalive-agent-header">
236
+ <h4>Claude</h4>
237
+ <label class="toggle-switch">
238
+ <input type="checkbox" id="keepalive-claude-enabled">
239
+ <span class="toggle-slider"></span>
240
+ </label>
241
+ </div>
242
+ <div class="keepalive-agent-row">
243
+ <label for="keepalive-claude-interval">Refresh Interval (hours)</label>
244
+ <input type="number" id="keepalive-claude-interval" class="form-input" min="1" max="24" value="6">
245
+ </div>
246
+ <div class="keepalive-agent-status" id="keepalive-claude-status-row">
247
+ <span id="keepalive-claude-status">Loading status...</span>
248
+ </div>
249
+ </div>
250
+
251
+ <!-- Codex -->
252
+ <div class="keepalive-agent-section">
253
+ <div class="keepalive-agent-header">
254
+ <h4>Codex</h4>
255
+ <label class="toggle-switch">
256
+ <input type="checkbox" id="keepalive-codex-enabled">
257
+ <span class="toggle-slider"></span>
258
+ </label>
259
+ </div>
260
+ <div class="keepalive-agent-row">
261
+ <label for="keepalive-codex-interval">Refresh Interval (hours)</label>
262
+ <input type="number" id="keepalive-codex-interval" class="form-input" min="1" max="24" value="8">
263
+ </div>
264
+ <div class="keepalive-agent-status" id="keepalive-codex-status-row">
265
+ <span id="keepalive-codex-status">Loading status...</span>
266
+ </div>
267
+ </div>
268
+
269
+ <!-- Gemini -->
270
+ <div class="keepalive-agent-section">
271
+ <div class="keepalive-agent-header">
272
+ <h4>Gemini</h4>
273
+ <label class="toggle-switch">
274
+ <input type="checkbox" id="keepalive-gemini-enabled">
275
+ <span class="toggle-slider"></span>
276
+ </label>
277
+ </div>
278
+ <div class="keepalive-agent-row">
279
+ <label for="keepalive-gemini-interval">Refresh Interval (hours)</label>
280
+ <input type="number" id="keepalive-gemini-interval" class="form-input" min="1" max="24" value="6">
281
+ </div>
282
+ <div class="keepalive-agent-status" id="keepalive-gemini-status-row">
283
+ <span id="keepalive-gemini-status">Loading status...</span>
284
+ </div>
285
+ </div>
286
+ </div>
287
+ </div>
288
+ <div class="card-actions">
289
+ <button type="button" class="btn-primary" id="save-keepalive-btn">Save</button>
290
+ </div>
291
+ </div>
292
+ </div>
293
+
294
+ <!-- API Keys Settings -->
295
+ <div id="section-apikeys" class="settings-panel" role="tabpanel" hidden>
296
+ <div class="content-card">
297
+ <div class="card-header">
298
+ <h3>API Keys</h3>
299
+ </div>
300
+ <div class="card-body" style="padding-top: 8px;">
301
+ <div id="apikeys-inline-message" class="inline-message" hidden></div>
302
+ <div class="apikeys-list">
303
+ <!-- Claude (Anthropic) -->
304
+ <div class="apikey-row">
305
+ <div class="apikey-header">
306
+ <span class="apikey-name">Claude</span>
307
+ <span class="apikey-provider">Anthropic</span>
308
+ </div>
309
+ <div class="apikey-controls">
310
+ <div class="apikey-input-group">
311
+ <input type="password" id="apikey-claude" class="form-input code-font" placeholder="sk-ant-...">
312
+ <button type="button" class="btn-icon apikey-toggle-visibility" data-target="apikey-claude" title="Toggle visibility">
313
+ <svg class="eye-open" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
314
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
315
+ <circle cx="12" cy="12" r="3"></circle>
316
+ </svg>
317
+ <svg class="eye-closed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
318
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>
319
+ <line x1="1" y1="1" x2="23" y2="23"></line>
320
+ </svg>
321
+ </button>
322
+ </div>
323
+ <label class="toggle-switch" title="Enable for AI tasks">
324
+ <input type="checkbox" id="apikey-claude-enabled">
325
+ <span class="toggle-slider"></span>
326
+ </label>
327
+ </div>
328
+ </div>
329
+
330
+ <!-- Codex (OpenAI) -->
331
+ <div class="apikey-row">
332
+ <div class="apikey-header">
333
+ <span class="apikey-name">Codex</span>
334
+ <span class="apikey-provider">OpenAI</span>
335
+ </div>
336
+ <div class="apikey-controls">
337
+ <div class="apikey-input-group">
338
+ <input type="password" id="apikey-codex" class="form-input code-font" placeholder="sk-...">
339
+ <button type="button" class="btn-icon apikey-toggle-visibility" data-target="apikey-codex" title="Toggle visibility">
340
+ <svg class="eye-open" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
341
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
342
+ <circle cx="12" cy="12" r="3"></circle>
343
+ </svg>
344
+ <svg class="eye-closed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
345
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>
346
+ <line x1="1" y1="1" x2="23" y2="23"></line>
347
+ </svg>
348
+ </button>
349
+ </div>
350
+ <label class="toggle-switch" title="Enable for AI tasks">
351
+ <input type="checkbox" id="apikey-codex-enabled">
352
+ <span class="toggle-slider"></span>
353
+ </label>
354
+ </div>
355
+ </div>
356
+
357
+ <!-- Gemini (Google) -->
358
+ <div class="apikey-row">
359
+ <div class="apikey-header">
360
+ <span class="apikey-name">Gemini</span>
361
+ <span class="apikey-provider">Google</span>
362
+ </div>
363
+ <div class="apikey-controls">
364
+ <div class="apikey-input-group">
365
+ <input type="password" id="apikey-gemini" class="form-input code-font" placeholder="AIza...">
366
+ <button type="button" class="btn-icon apikey-toggle-visibility" data-target="apikey-gemini" title="Toggle visibility">
367
+ <svg class="eye-open" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
368
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
369
+ <circle cx="12" cy="12" r="3"></circle>
370
+ </svg>
371
+ <svg class="eye-closed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
372
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>
373
+ <line x1="1" y1="1" x2="23" y2="23"></line>
374
+ </svg>
375
+ </button>
376
+ </div>
377
+ <label class="toggle-switch" title="Enable for AI tasks">
378
+ <input type="checkbox" id="apikey-gemini-enabled">
379
+ <span class="toggle-slider"></span>
380
+ </label>
381
+ </div>
382
+ </div>
383
+ </div>
384
+ </div>
385
+ <div class="card-actions">
386
+ <button type="button" class="btn-primary" id="save-apikeys-btn">Save</button>
387
+ </div>
388
+ </div>
389
+ </div>
390
+
391
+ <!-- Provider Authentication Settings -->
392
+ <div id="section-provider-auth" class="settings-panel" role="tabpanel" hidden>
393
+ <div class="content-card">
394
+ <div class="card-header">
395
+ <h3>Provider Authentication</h3>
396
+ </div>
397
+ <div class="card-body" style="padding-top: 8px;">
398
+ <div id="provider-auth-inline-message" class="inline-message" hidden></div>
399
+ <p class="text-muted" style="margin-bottom: 16px;">Sign in to AI provider accounts. Multiple accounts can be connected per provider.</p>
400
+
401
+ <div class="provider-auth-list">
402
+ <!-- Claude (Anthropic) -->
403
+ <div class="provider-auth-section" data-provider="claude">
404
+ <div class="provider-auth-header-row">
405
+ <div class="provider-auth-title">
406
+ <span class="provider-name">Claude</span>
407
+ <span class="provider-company">Anthropic</span>
408
+ </div>
409
+ <button class="btn-primary btn-small" id="provider-claude-add-btn">
410
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 4px; vertical-align: -1px;">
411
+ <line x1="12" y1="5" x2="12" y2="19"></line>
412
+ <line x1="5" y1="12" x2="19" y2="12"></line>
413
+ </svg>
414
+ Add Account
415
+ </button>
416
+ </div>
417
+ <div class="provider-accounts-list" id="provider-claude-accounts">
418
+ <div class="provider-no-accounts">No accounts connected</div>
419
+ </div>
420
+ </div>
421
+
422
+ <!-- Codex (OpenAI) -->
423
+ <div class="provider-auth-section" data-provider="codex">
424
+ <div class="provider-auth-header-row">
425
+ <div class="provider-auth-title">
426
+ <span class="provider-name">Codex</span>
427
+ <span class="provider-company">OpenAI</span>
428
+ </div>
429
+ <button class="btn-primary btn-small" id="provider-codex-add-btn">
430
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 4px; vertical-align: -1px;">
431
+ <line x1="12" y1="5" x2="12" y2="19"></line>
432
+ <line x1="5" y1="12" x2="19" y2="12"></line>
433
+ </svg>
434
+ Add Account
435
+ </button>
436
+ </div>
437
+ <div class="provider-accounts-list" id="provider-codex-accounts">
438
+ <div class="provider-no-accounts">No accounts connected</div>
439
+ </div>
440
+ </div>
441
+
442
+ <!-- Gemini (Google) -->
443
+ <div class="provider-auth-section" data-provider="gemini">
444
+ <div class="provider-auth-header-row">
445
+ <div class="provider-auth-title">
446
+ <span class="provider-name">Gemini</span>
447
+ <span class="provider-company">Google</span>
448
+ </div>
449
+ <button class="btn-primary btn-small" id="provider-gemini-add-btn">
450
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 4px; vertical-align: -1px;">
451
+ <line x1="12" y1="5" x2="12" y2="19"></line>
452
+ <line x1="5" y1="12" x2="19" y2="12"></line>
453
+ </svg>
454
+ Add Account
455
+ </button>
456
+ </div>
457
+ <div class="provider-accounts-list" id="provider-gemini-accounts">
458
+ <div class="provider-no-accounts">No accounts connected</div>
459
+ </div>
460
+ </div>
461
+ </div>
462
+ </div>
463
+ </div>
464
+ </div>
465
+
466
+ <!-- Model Configuration Settings -->
467
+ <div id="section-models" class="settings-panel" role="tabpanel" hidden>
468
+ <div class="content-card">
469
+ <div class="card-header">
470
+ <h3>Model Configuration</h3>
471
+ </div>
472
+ <div class="card-body">
473
+ <div id="models-inline-message" class="inline-message" hidden></div>
474
+ <p class="text-muted" style="margin-bottom: 16px;">Configure which models to use for each AI provider</p>
475
+
476
+ <div class="form-single-column">
477
+ <div class="form-row">
478
+ <label for="model-claude">Claude Model</label>
479
+ <div id="model-claude-container"></div>
480
+ </div>
481
+ <div class="form-row">
482
+ <label for="model-codex">Codex Model</label>
483
+ <div id="model-codex-container"></div>
484
+ </div>
485
+ <div class="form-row" id="codex-reasoning-row" hidden>
486
+ <label for="model-codex-reasoning">Codex Reasoning Level</label>
487
+ <div id="model-codex-reasoning-container"></div>
488
+ </div>
489
+ <div class="form-row">
490
+ <label for="model-gemini">Gemini Model</label>
491
+ <div id="model-gemini-container"></div>
492
+ </div>
493
+ </div>
494
+ </div>
495
+ <div class="card-actions">
496
+ <button type="button" class="btn-secondary" id="refresh-models-btn">Refresh Models</button>
497
+ <button type="button" class="btn-primary" id="save-models-btn">Save</button>
498
+ </div>
499
+ </div>
500
+ </div>
501
+
502
+ <!-- Email (SMTP) Settings -->
503
+ <div id="section-email" class="settings-panel" role="tabpanel" hidden>
504
+ <div class="content-card">
505
+ <div class="card-header">
506
+ <h3>Email Settings (SMTP)</h3>
507
+ </div>
508
+ <div class="card-body">
509
+ <div id="email-inline-message" class="inline-message" hidden></div>
510
+ <div class="form-single-column">
511
+ <div class="form-row">
512
+ <label for="email-host">SMTP Host</label>
513
+ <input type="text" id="email-host" class="form-input" placeholder="smtp.example.com">
514
+ </div>
515
+ <div class="form-row">
516
+ <label for="email-port">SMTP Port</label>
517
+ <input type="number" id="email-port" class="form-input" value="587" style="max-width: 120px;">
518
+ </div>
519
+ <div class="form-row">
520
+ <label for="email-secure">Use TLS/SSL</label>
521
+ <label class="toggle-switch">
522
+ <input type="checkbox" id="email-secure">
523
+ <span class="toggle-slider"></span>
524
+ </label>
525
+ <span class="form-hint">Enable for port 465, disable for port 587 with STARTTLS</span>
526
+ </div>
527
+ <div class="form-row">
528
+ <label for="email-user">Username</label>
529
+ <input type="text" id="email-user" class="form-input" placeholder="user@example.com">
530
+ </div>
531
+ <div class="form-row">
532
+ <label for="email-password">Password</label>
533
+ <div class="apikey-input-group">
534
+ <input type="password" id="email-password" class="form-input" placeholder="Enter password or leave blank to keep existing">
535
+ <button type="button" class="btn-icon apikey-toggle-visibility" data-target="email-password" title="Toggle visibility">
536
+ <svg class="eye-open" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
537
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
538
+ <circle cx="12" cy="12" r="3"></circle>
539
+ </svg>
540
+ <svg class="eye-closed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
541
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>
542
+ <line x1="1" y1="1" x2="23" y2="23"></line>
543
+ </svg>
544
+ </button>
545
+ </div>
546
+ <span id="email-password-status" class="form-hint"></span>
547
+ </div>
548
+ <div class="form-row">
549
+ <label for="email-from">From Address</label>
550
+ <input type="email" id="email-from" class="form-input" placeholder="noreply@example.com">
551
+ </div>
552
+ <div class="form-row">
553
+ <label for="email-from-name">From Name</label>
554
+ <input type="text" id="email-from-name" class="form-input" placeholder="CoderFlow">
555
+ </div>
556
+ </div>
557
+
558
+ <div class="email-test-section" style="margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--color-border);">
559
+ <div class="subsection-header" style="margin-bottom: 12px;">
560
+ <h4 style="margin: 0;">Test Configuration</h4>
561
+ </div>
562
+ <div class="form-single-column">
563
+ <div class="form-row">
564
+ <label for="email-test-recipient">Test Recipient</label>
565
+ <input type="email" id="email-test-recipient" class="form-input code-font" placeholder="your@email.com">
566
+ </div>
567
+ <div class="form-row">
568
+ <label></label>
569
+ <div style="display: flex; gap: 8px;">
570
+ <button type="button" class="btn-secondary btn-small" id="email-test-connection-btn">
571
+ Test Connection
572
+ </button>
573
+ <button type="button" class="btn-secondary btn-small" id="email-send-test-btn">
574
+ Send Test Email
575
+ </button>
576
+ </div>
577
+ </div>
578
+ <div class="form-row" id="email-test-result-row" hidden>
579
+ <label></label>
580
+ <div id="email-test-result" class="email-test-result"></div>
581
+ </div>
582
+ </div>
583
+ </div>
584
+ </div>
585
+ <div class="card-actions">
586
+ <button type="button" class="btn-primary" id="save-email-btn">Save</button>
587
+ </div>
588
+ </div>
589
+ </div>
590
+
591
+ <!-- Git Providers Settings -->
592
+ <div id="section-git-providers" class="settings-panel" role="tabpanel" hidden>
593
+ <div class="content-card">
594
+ <div class="card-header">
595
+ <h3>Global Git Providers</h3>
596
+ </div>
597
+ <div class="card-body">
598
+ <div id="git-providers-inline-message" class="inline-message" hidden></div>
599
+ <p class="text-muted" style="margin-bottom: 16px;">Configure global git providers that can be used by any environment. Environment-specific providers can be configured in each environment's settings.</p>
600
+
601
+ <!-- Token Expiration Setting -->
602
+ <div class="form-single-column" style="margin-bottom: 20px;">
603
+ <div class="form-row">
604
+ <label for="git-token-expiration">Container Token Expiration</label>
605
+ <div class="token-expiry-controls">
606
+ <input type="number" id="git-token-expiration" class="form-input" min="1" value="7" style="width: 80px;">
607
+ <span class="token-expiry-suffix">days</span>
608
+ <button type="button" class="btn-secondary btn-small" id="save-git-token-expiration-btn">Save</button>
609
+ </div>
610
+ <span class="form-hint">Containers can access Git credentials until expiration; start a new task to renew</span>
611
+ </div>
612
+ </div>
613
+
614
+ <div class="git-providers-list" id="global-git-providers-list">
615
+ <!-- Git providers will be populated here -->
616
+ </div>
617
+
618
+ <div class="git-provider-add-section" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--color-border);">
619
+ <button type="button" class="btn-secondary" id="add-global-git-provider-btn">
620
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 4px;">
621
+ <line x1="12" y1="5" x2="12" y2="19"></line>
622
+ <line x1="5" y1="12" x2="19" y2="12"></line>
623
+ </svg>
624
+ Add Git Provider
625
+ </button>
626
+ </div>
627
+ </div>
628
+ </div>
629
+ </div>
630
+
631
+ <!-- Single Sign-On Settings -->
632
+ <div id="section-sso" class="settings-panel" role="tabpanel" hidden>
633
+ <div class="content-card">
634
+ <div class="card-header">
635
+ <h3>Single Sign-On (OIDC)</h3>
636
+ </div>
637
+ <div class="card-body" id="sso-config">
638
+ <!-- Inline message area -->
639
+ <div id="sso-inline-message" class="inline-message" hidden></div>
640
+
641
+ <!-- Tabs -->
642
+ <div class="sso-tabs">
643
+ <button type="button" class="sso-tab active" data-tab="connection">Connection</button>
644
+ <button type="button" class="sso-tab" data-tab="provisioning">User Provisioning</button>
645
+ </div>
646
+
647
+ <!-- Connection Tab -->
648
+ <div id="sso-tab-connection" class="sso-tab-content active">
649
+ <div class="form-single-column">
650
+ <div class="form-row">
651
+ <label for="sso-enabled">Enable SSO</label>
652
+ <label class="toggle-switch">
653
+ <input type="checkbox" id="sso-enabled">
654
+ <span class="toggle-slider"></span>
655
+ </label>
656
+ </div>
657
+
658
+ <div class="form-row">
659
+ <label for="sso-provider">Identity Provider</label>
660
+ <div id="sso-provider-container"></div>
661
+ </div>
662
+
663
+ <div class="form-row">
664
+ <label for="sso-display-name">Button Text</label>
665
+ <input type="text" id="sso-display-name" class="form-input" placeholder="e.g., Sign in with Microsoft">
666
+ </div>
667
+
668
+ <div class="form-row">
669
+ <label for="sso-client-id">Client ID <span class="required">*</span></label>
670
+ <input type="text" id="sso-client-id" class="form-input code-font" placeholder="Application/Client ID from your IdP">
671
+ </div>
672
+
673
+ <div class="form-row">
674
+ <label for="sso-client-secret">Client Secret <span class="required">*</span></label>
675
+ <div>
676
+ <input type="password" id="sso-client-secret" class="form-input code-font" placeholder="Client secret from your IdP">
677
+ <span id="sso-secret-hint" class="form-hint" style="display: none; margin-top: 4px;">Leave blank to keep existing secret</span>
678
+ </div>
679
+ </div>
680
+
681
+ <div class="form-row">
682
+ <label for="sso-issuer">Issuer URL <span class="required">*</span></label>
683
+ <div>
684
+ <input type="text" id="sso-issuer" class="form-input code-font" placeholder="e.g., https://login.microsoftonline.com/{tenant-id}/v2.0">
685
+ <span class="form-hint" style="margin-top: 4px;">The OIDC discovery URL for your identity provider</span>
686
+ </div>
687
+ </div>
688
+
689
+ <div class="form-row">
690
+ <label></label>
691
+ <div>
692
+ <button type="button" class="btn-secondary btn-small" id="sso-test-btn">
693
+ Test Connection
694
+ </button>
695
+ <div id="sso-test-result" class="sso-test-result" hidden></div>
696
+ </div>
697
+ </div>
698
+ </div>
699
+ </div>
700
+
701
+ <!-- User Provisioning Tab -->
702
+ <div id="sso-tab-provisioning" class="sso-tab-content">
703
+ <div class="form-single-column">
704
+ <div class="form-row">
705
+ <label for="sso-auto-provision">Auto-provision users</label>
706
+ <label class="toggle-switch">
707
+ <input type="checkbox" id="sso-auto-provision" checked>
708
+ <span class="toggle-slider"></span>
709
+ </label>
710
+ </div>
711
+ <p class="sso-field-description">Automatically create user accounts when someone logs in via SSO for the first time.</p>
712
+
713
+ <div class="form-row">
714
+ <label for="sso-default-role">Default Role</label>
715
+ <div id="sso-default-role-container"></div>
716
+ </div>
717
+ <p class="sso-field-description">Role assigned to auto-provisioned users. Can be changed later per user.</p>
718
+
719
+ <div class="form-row">
720
+ <label for="sso-allow-local">Allow local login</label>
721
+ <label class="toggle-switch">
722
+ <input type="checkbox" id="sso-allow-local" checked>
723
+ <span class="toggle-slider"></span>
724
+ </label>
725
+ </div>
726
+ <p class="sso-field-description">Show username/password form alongside SSO button. Disable for SSO-only authentication.</p>
727
+ </div>
728
+ </div>
729
+ </div>
730
+ <div class="card-actions">
731
+ <button type="button" class="btn-danger btn-small" id="sso-remove-btn" style="margin-right: auto;" hidden>Remove SSO</button>
732
+ <button type="button" class="btn-primary" id="save-sso-btn">Save</button>
733
+ </div>
734
+ </div>
735
+ </div>
736
+ </section>
737
+ </div>
738
+ </main>
739
+
740
+ <!-- Provider Sign-In Flow Modal -->
741
+ <div id="provider-signin-modal" class="modal" hidden>
742
+ <div class="modal-overlay"></div>
743
+ <div class="modal-content">
744
+ <div class="modal-header">
745
+ <h2 id="provider-signin-title">Sign in with Provider</h2>
746
+ <button type="button" class="modal-close" aria-label="Close">&times;</button>
747
+ </div>
748
+ <div class="modal-body">
749
+ <div class="signin-steps">
750
+ <div class="signin-step">
751
+ <span class="step-number">1</span>
752
+ <span class="step-text">Open the secure sign-in page</span>
753
+ </div>
754
+ <button class="btn-primary" id="provider-signin-open-btn" style="width: 100%; margin: 8px 0 16px 0;">
755
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 8px; vertical-align: -2px;">
756
+ <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
757
+ <polyline points="15 3 21 3 21 9"></polyline>
758
+ <line x1="10" y1="14" x2="21" y2="3"></line>
759
+ </svg>
760
+ Open Sign-In Page
761
+ </button>
762
+
763
+ <div class="signin-step">
764
+ <span class="step-number">2</span>
765
+ <span class="step-text" id="provider-signin-instructions">
766
+ Complete sign-in and copy the authorization code
767
+ </span>
768
+ </div>
769
+
770
+ <!-- Secure redirect notice for URL-copy flow (Codex/Gemini) -->
771
+ <div id="provider-signin-localhost-notice" class="secure-redirect-notice" hidden>
772
+ <div class="secure-redirect-header">
773
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
774
+ <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
775
+ <path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
776
+ </svg>
777
+ <span>Secure Local Redirect</span>
778
+ </div>
779
+ <p>After signing in, your browser will redirect to a local address. The page won't load &mdash; this is expected. This secure method keeps your authorization tokens private.</p>
780
+ <div class="secure-redirect-instruction">
781
+ <strong>Copy the complete URL</strong> from your browser's address bar and paste it below.
782
+ </div>
783
+ </div>
784
+
785
+ <div class="form-row" style="margin-top: 12px; grid-template-columns: auto 1fr; gap: 8px;">
786
+ <label for="provider-signin-input" id="provider-signin-label">Authorization Code or URL</label>
787
+ <input type="text" id="provider-signin-input" class="form-input code-font"
788
+ placeholder="Paste code or URL here">
789
+ </div>
790
+
791
+ <div class="signin-step" style="margin-top: 16px;">
792
+ <span class="step-number">3</span>
793
+ <span class="step-text">Name this account</span>
794
+ </div>
795
+ <div class="form-row" style="margin-top: 8px; grid-template-columns: auto 1fr; gap: 8px;">
796
+ <label for="provider-signin-label-input">Account Label</label>
797
+ <input type="text" id="provider-signin-label-input" class="form-input"
798
+ placeholder="e.g., Production, Development, Team">
799
+ </div>
800
+ </div>
801
+ </div>
802
+ <div class="modal-actions">
803
+ <button type="button" class="btn-secondary" id="provider-signin-cancel-btn">Cancel</button>
804
+ <button type="button" class="btn-primary" id="provider-signin-submit-btn">Complete Sign-In</button>
805
+ </div>
806
+ </div>
807
+ </div>
808
+
809
+ <!-- Provider Rename Modal -->
810
+ <div id="provider-rename-modal" class="modal" hidden>
811
+ <div class="modal-overlay"></div>
812
+ <div class="modal-content modal-content-narrow">
813
+ <div class="modal-header">
814
+ <h2>Rename Account</h2>
815
+ <button type="button" class="modal-close" aria-label="Close">&times;</button>
816
+ </div>
817
+ <div class="modal-body">
818
+ <label for="provider-rename-input" style="display: block; margin-bottom: 8px; font-weight: 500;">Account Name</label>
819
+ <input type="text" id="provider-rename-input" class="form-input" placeholder="Enter account name">
820
+ </div>
821
+ <div class="modal-actions">
822
+ <button type="button" class="btn-secondary" id="provider-rename-cancel-btn">Cancel</button>
823
+ <button type="button" class="btn-primary" id="provider-rename-save-btn">Rename</button>
824
+ </div>
825
+ </div>
826
+ </div>
827
+
828
+ <!-- Add Provider Type Selection Modal -->
829
+ <div id="add-provider-type-modal" class="modal" hidden>
830
+ <div class="modal-overlay"></div>
831
+ <div class="modal-content modal-content-narrow">
832
+ <div class="modal-header">
833
+ <h2>Add Git Provider</h2>
834
+ <button type="button" class="modal-close" aria-label="Close">&times;</button>
835
+ </div>
836
+ <div class="modal-body">
837
+ <p class="modal-description">Choose the type of provider to add:</p>
838
+ <div class="provider-type-options">
839
+ <button type="button" class="provider-type-option" id="add-provider-github-btn">
840
+ <div class="provider-type-icon">
841
+ <svg width="24" height="24" viewBox="0 0 98 96"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="currentColor"/></svg>
842
+ </div>
843
+ <div class="provider-type-info">
844
+ <strong>GitHub</strong>
845
+ <span class="provider-type-desc">GitHub App</span>
846
+ </div>
847
+ </button>
848
+ <button type="button" class="provider-type-option" id="add-provider-azure-btn">
849
+ <div class="provider-type-icon">
850
+ <svg width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M13.05 4.24L6.56 18.05l2.09.81L18 9.77l.3-.41-5.25-5.12zm-4.21 2.6l5.79 5.64-.42.4-9.28 2.6 3.91-8.64zm-1.79 10.1l9.31-2.59.43-.39 1.61 1.57L4.67 19.2l2.38-2.26z"/></svg>
851
+ </div>
852
+ <div class="provider-type-info">
853
+ <strong>Azure DevOps</strong>
854
+ <span class="provider-type-desc">Service Principal</span>
855
+ </div>
856
+ </button>
857
+ </div>
858
+ </div>
859
+ <div class="modal-actions">
860
+ <button type="button" class="btn-secondary" id="add-provider-type-cancel-btn">Cancel</button>
861
+ </div>
862
+ </div>
863
+ </div>
864
+
865
+ <!-- GitHub App Setup Wizard Modal -->
866
+ <div id="github-app-setup-wizard-modal" class="modal" hidden>
867
+ <div class="modal-overlay"></div>
868
+ <div class="modal-content modal-medium">
869
+ <div class="modal-header">
870
+ <h2 id="github-setup-wizard-title">Create GitHub App</h2>
871
+ <button type="button" class="modal-close" aria-label="Close">&times;</button>
872
+ </div>
873
+ <div class="modal-body">
874
+ <div id="github-setup-wizard-error" class="modal-error" hidden></div>
875
+
876
+ <!-- Step 1: Configuration -->
877
+ <div id="github-setup-step-1" class="wizard-step">
878
+ <p class="modal-description">Create a GitHub App for repository access. When you click Next, you'll be redirected to GitHub to approve and install the app.</p>
879
+ <p class="modal-description text-muted" style="font-size: 0.9em;">
880
+ Note: You must be <a href="https://github.com/login" target="_blank">logged into GitHub</a> before proceeding.
881
+ </p>
882
+ <div class="form-single-column">
883
+ <div class="form-row">
884
+ <label for="github-setup-provider-name">Provider Name <span class="required">*</span></label>
885
+ <input type="text" id="github-setup-provider-name" class="form-input code-font" placeholder="e.g., github-myorg" required>
886
+ <span class="form-hint">Lowercase alphanumeric with hyphens. Used to reference this provider in environments.</span>
887
+ </div>
888
+ <div class="form-row">
889
+ <label for="github-setup-app-name">GitHub App Name <span class="required">*</span></label>
890
+ <input type="text" id="github-setup-app-name" class="form-input" placeholder="e.g., CoderFlow-MyOrg" required>
891
+ <span class="form-hint">Name for the GitHub App (visible on GitHub)</span>
892
+ </div>
893
+ <div class="form-row">
894
+ <label for="github-setup-description">Description</label>
895
+ <input type="text" id="github-setup-description" class="form-input" placeholder="e.g., CoderFlow integration for repository access">
896
+ </div>
897
+ <div class="form-row">
898
+ <label for="github-setup-account-type">Account Type <span class="required">*</span></label>
899
+ <div id="github-setup-account-type-container"></div>
900
+ </div>
901
+ <div class="form-row" id="github-setup-org-row">
902
+ <label for="github-setup-org-name">Organization Name <span class="required">*</span></label>
903
+ <input type="text" id="github-setup-org-name" class="form-input code-font" placeholder="e.g., my-organization">
904
+ <span class="form-hint">The GitHub organization where the app will be created</span>
905
+ </div>
906
+ </div>
907
+ </div>
908
+
909
+ <!-- Hidden form for manifest submission (auto-submitted after validation) -->
910
+ <form id="github-setup-manifest-form" method="post" style="display: none;">
911
+ <input type="hidden" name="manifest" id="github-setup-manifest-input">
912
+ </form>
913
+
914
+ </div>
915
+ <div class="modal-actions">
916
+ <button type="button" class="btn-secondary" id="github-setup-cancel-btn">Cancel</button>
917
+ <button type="button" class="btn-primary" id="github-setup-next-btn">Next</button>
918
+ </div>
919
+ </div>
920
+ </div>
921
+
922
+ <!-- Git Provider Modal -->
923
+ <div id="git-provider-modal" class="modal" hidden>
924
+ <div class="modal-overlay"></div>
925
+ <div class="modal-content">
926
+ <div class="modal-header">
927
+ <h2 id="git-provider-modal-title">Add Git Provider</h2>
928
+ <button type="button" class="modal-close" aria-label="Close">&times;</button>
929
+ </div>
930
+ <div class="modal-body">
931
+ <div id="git-provider-modal-error" class="modal-error" hidden></div>
932
+ <div class="form-single-column">
933
+ <div class="form-row">
934
+ <label for="git-provider-name">Provider Name <span id="git-provider-name-required" class="required">*</span></label>
935
+ <input type="text" id="git-provider-name" class="form-input code-font" placeholder="e.g., github-myorg" required>
936
+ <span id="git-provider-name-hint" class="form-hint">Lowercase alphanumeric with hyphens</span>
937
+ </div>
938
+ <div class="form-row">
939
+ <label for="git-provider-type">Provider Type <span id="git-provider-type-required" class="required">*</span></label>
940
+ <div id="git-provider-type-container"></div>
941
+ </div>
942
+ <div id="github-provider-fields" class="form-single-column">
943
+ <div class="form-row">
944
+ <label for="git-provider-app-id">App ID <span class="required">*</span></label>
945
+ <input type="text" id="git-provider-app-id" class="form-input code-font" placeholder="e.g., 123456" required>
946
+ </div>
947
+ <div class="form-row">
948
+ <label for="git-provider-installation-id">Installation ID <span class="required">*</span></label>
949
+ <input type="text" id="git-provider-installation-id" class="form-input code-font" placeholder="e.g., 78901234" required>
950
+ </div>
951
+ <!-- GitHub Installation Settings Button (only visible in edit mode when URL is available) -->
952
+ <div id="github-installation-link-row" class="form-row" hidden>
953
+ <label>Installation Settings</label>
954
+ <div>
955
+ <button type="button" id="github-installation-btn" class="btn-secondary btn-small">Show on GitHub</button>
956
+ </div>
957
+ </div>
958
+ <!-- OAuth Credentials (for User Access Token flows) -->
959
+ <div id="github-oauth-fields" class="form-single-column" hidden>
960
+ <div class="form-row">
961
+ <label for="git-provider-oauth-client-id">Client ID <span id="git-provider-oauth-client-id-required" class="required" hidden>*</span></label>
962
+ <input type="text" id="git-provider-oauth-client-id" class="form-input code-font">
963
+ </div>
964
+ <div class="form-row">
965
+ <label for="git-provider-oauth-client-secret">Client Secret</label>
966
+ <input type="text" id="git-provider-oauth-client-secret" class="form-input code-font" placeholder="(Leave blank to keep current secret)">
967
+ </div>
968
+ </div>
969
+ <div class="form-row">
970
+ <label for="git-provider-private-key">Private Key (PEM) <span id="git-provider-private-key-required" class="required">*</span></label>
971
+ <textarea id="git-provider-private-key" class="form-input code-font" rows="8" placeholder="-----BEGIN RSA PRIVATE KEY-----&#10;...&#10;-----END RSA PRIVATE KEY-----"></textarea>
972
+ <div class="form-row-actions" style="margin-top: 8px;">
973
+ <button type="button" class="btn-secondary btn-small" id="git-provider-import-key-btn">
974
+ <span>📁</span> Import from file...
975
+ </button>
976
+ <input type="file" id="git-provider-key-input" hidden accept=".pem,.key">
977
+ </div>
978
+ </div>
979
+ </div>
980
+ <div id="azure-devops-provider-fields" class="form-single-column" hidden>
981
+ <div class="form-row">
982
+ <label for="git-provider-organization">Organization <span class="required">*</span></label>
983
+ <input type="text" id="git-provider-organization" class="form-input code-font" placeholder="e.g., myorg" required>
984
+ <span class="form-hint">Azure DevOps organization name</span>
985
+ </div>
986
+ <div class="form-row">
987
+ <label for="git-provider-tenant-id">Tenant ID <span class="required">*</span></label>
988
+ <input type="text" id="git-provider-tenant-id" class="form-input code-font" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" required>
989
+ <span class="form-hint">Microsoft Entra ID tenant ID (GUID format)</span>
990
+ </div>
991
+ <div class="form-row">
992
+ <label for="git-provider-client-id">Client ID <span class="required">*</span></label>
993
+ <input type="text" id="git-provider-client-id" class="form-input code-font" placeholder="yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" required>
994
+ <span class="form-hint">App Registration client ID (GUID format)</span>
995
+ </div>
996
+ <div class="form-row">
997
+ <label for="git-provider-auth-method">Authentication Method <span class="required">*</span></label>
998
+ <div id="git-provider-auth-method-container"></div>
999
+ </div>
1000
+ <div id="azure-secret-fields" class="form-row">
1001
+ <label for="git-provider-client-secret">Client Secret <span class="required">*</span></label>
1002
+ <input type="text" id="git-provider-client-secret" class="form-input code-font" placeholder="Enter client secret">
1003
+ </div>
1004
+ <div id="azure-certificate-fields" class="form-row" hidden>
1005
+ <label for="git-provider-certificate">Certificate (PEM with Private Key) <span class="required">*</span></label>
1006
+ <textarea id="git-provider-certificate" class="form-input code-font" rows="8" placeholder="-----BEGIN CERTIFICATE-----&#10;...&#10;-----END CERTIFICATE-----&#10;-----BEGIN PRIVATE KEY-----&#10;...&#10;-----END PRIVATE KEY-----"></textarea>
1007
+ <div class="form-row-actions" style="margin-top: 8px;">
1008
+ <button type="button" class="btn-secondary btn-small" id="git-provider-import-cert-btn">
1009
+ <span>📁</span> Import from file...
1010
+ </button>
1011
+ <input type="file" id="git-provider-cert-input" hidden accept=".pem,.crt,.cer,.key">
1012
+ </div>
1013
+ </div>
1014
+ </div>
1015
+ </div>
1016
+ </div>
1017
+ <div class="modal-actions">
1018
+ <button type="button" class="btn-secondary" id="git-provider-test-btn">Test Connection</button>
1019
+ <button type="button" class="btn-secondary" id="git-provider-cancel-btn">Cancel</button>
1020
+ <button type="button" class="btn-primary" id="git-provider-save-btn">Save Provider</button>
1021
+ </div>
1022
+ </div>
1023
+ </div>
1024
+
1025
+ <!-- Delete Git Provider Modal -->
1026
+ <div id="delete-git-provider-modal" class="modal" hidden>
1027
+ <div class="modal-overlay"></div>
1028
+ <div class="modal-content modal-content-narrow">
1029
+ <div class="modal-header">
1030
+ <h2>Delete Git Provider</h2>
1031
+ <button type="button" class="modal-close" aria-label="Close">&times;</button>
1032
+ </div>
1033
+ <div class="modal-body">
1034
+ <p>Are you sure you want to delete the git provider "<strong id="delete-git-provider-name"></strong>"?</p>
1035
+ <p class="text-muted">This action cannot be undone.</p>
1036
+ </div>
1037
+ <div class="modal-actions">
1038
+ <button type="button" class="btn-secondary" id="delete-git-provider-cancel-btn">Cancel</button>
1039
+ <button type="button" class="btn-danger" id="delete-git-provider-confirm-btn">Delete</button>
1040
+ </div>
1041
+ </div>
1042
+ </div>
1043
+ </body>
1044
+ </html>