@profoundlogic/coderflow-server 0.2.6 → 0.2.8

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 (138) hide show
  1. package/dist/coder-server.js +1 -1
  2. package/dist/config.js +1 -1
  3. package/dist/lib/agent-keepalive.js +1 -1
  4. package/dist/lib/api-keys.js +1 -1
  5. package/dist/lib/apiKeys.js +1 -1
  6. package/dist/lib/app-server-ports.js +1 -1
  7. package/dist/lib/auto-judge.js +1 -1
  8. package/dist/lib/basic-auth.js +1 -1
  9. package/dist/lib/build-history.js +1 -1
  10. package/dist/lib/build-output-service.js +1 -1
  11. package/dist/lib/build-scheduler.js +1 -1
  12. package/dist/lib/build-service.js +1 -1
  13. package/dist/lib/ca-certificates.js +1 -1
  14. package/dist/lib/claude-oauth-refresh.js +1 -1
  15. package/dist/lib/cli/build.js +1 -1
  16. package/dist/lib/cli/config-command.js +1 -1
  17. package/dist/lib/cli/config.js +1 -1
  18. package/dist/lib/cli/create-user.js +1 -1
  19. package/dist/lib/cli/init.js +1 -1
  20. package/dist/lib/cli/jira.js +1 -1
  21. package/dist/lib/cli/license.js +1 -1
  22. package/dist/lib/cli/server-manager.js +1 -1
  23. package/dist/lib/container-tokens.js +1 -1
  24. package/dist/lib/data-dir.js +1 -1
  25. package/dist/lib/deployment-history.js +1 -1
  26. package/dist/lib/deployment-service.js +1 -1
  27. package/dist/lib/docker-utils.js +1 -1
  28. package/dist/lib/email.js +1 -1
  29. package/dist/lib/emailTemplates.js +1 -1
  30. package/dist/lib/entitlement.js +1 -1
  31. package/dist/lib/fetch-utils.js +1 -1
  32. package/dist/lib/git-commit-details-route.js +1 -1
  33. package/dist/lib/git-history-diff-guardrails.js +1 -1
  34. package/dist/lib/git-provider-service.js +1 -1
  35. package/dist/lib/git-provider-setup/github-setup-handler.js +1 -1
  36. package/dist/lib/git-provider-setup/index.js +1 -1
  37. package/dist/lib/git-provider-setup/setup-factory.js +1 -1
  38. package/dist/lib/git-provider-setup/setup-interface.js +1 -1
  39. package/dist/lib/git-providers/azure-devops-provider.js +1 -1
  40. package/dist/lib/git-providers/github-app-provider.js +1 -1
  41. package/dist/lib/git-providers/index.js +1 -1
  42. package/dist/lib/git-providers/provider-factory.js +1 -1
  43. package/dist/lib/git-providers/provider-interface.js +1 -1
  44. package/dist/lib/github-urls.js +1 -1
  45. package/dist/lib/group-objective-linking.js +1 -1
  46. package/dist/lib/jira-client.js +1 -1
  47. package/dist/lib/judge-blinding.js +1 -1
  48. package/dist/lib/logger.js +1 -1
  49. package/dist/lib/model-fetcher.js +1 -1
  50. package/dist/lib/notifications.js +1 -1
  51. package/dist/lib/oidc-auth.js +1 -1
  52. package/dist/lib/oidc-device-flow.js +1 -1
  53. package/dist/lib/passwordTokens.js +1 -1
  54. package/dist/lib/pin-cascade.js +1 -1
  55. package/dist/lib/provider-accounts.js +1 -1
  56. package/dist/lib/provider-oauth.js +1 -1
  57. package/dist/lib/provider-profile.js +1 -1
  58. package/dist/lib/provider-token-refresh.js +1 -1
  59. package/dist/lib/request-url.js +1 -1
  60. package/dist/lib/rewind.js +1 -1
  61. package/dist/lib/roles.js +1 -1
  62. package/dist/lib/secrets.js +1 -1
  63. package/dist/lib/setup-repo-git-auth.js +1 -1
  64. package/dist/lib/state-capture.js +1 -1
  65. package/dist/lib/static-files.js +1 -1
  66. package/dist/lib/task-name-generator.js +1 -1
  67. package/dist/lib/user-git-oauth.js +1 -1
  68. package/dist/lib/user-git-tokens.js +1 -1
  69. package/dist/lib/users.js +1 -1
  70. package/dist/middleware/requireAuth.js +1 -1
  71. package/dist/middleware/requireInit.js +1 -1
  72. package/dist/middleware/requirePermission.js +1 -1
  73. package/dist/package.json +1 -1
  74. package/dist/routes/apiKeys.js +1 -1
  75. package/dist/routes/auth-oidc.js +1 -1
  76. package/dist/routes/auth.js +1 -1
  77. package/dist/routes/build.js +1 -1
  78. package/dist/routes/containers.js +1 -1
  79. package/dist/routes/deploy-task.js +1 -1
  80. package/dist/routes/environment-management.js +1 -1
  81. package/dist/routes/environments.js +1 -1
  82. package/dist/routes/external-skills.js +1 -1
  83. package/dist/routes/git-credentials.js +1 -1
  84. package/dist/routes/git-oauth.js +1 -1
  85. package/dist/routes/git-provider-setup.js +1 -1
  86. package/dist/routes/health.js +1 -1
  87. package/dist/routes/jira.js +1 -1
  88. package/dist/routes/objective-management.js +1 -1
  89. package/dist/routes/password.js +1 -1
  90. package/dist/routes/prompt.js +1 -1
  91. package/dist/routes/provider-auth.js +1 -1
  92. package/dist/routes/qa.js +1 -1
  93. package/dist/routes/settings.js +1 -1
  94. package/dist/routes/skill-management.js +1 -1
  95. package/dist/routes/skills.js +1 -1
  96. package/dist/routes/tasks.js +1 -1
  97. package/dist/routes/templates.js +1 -1
  98. package/dist/routes/test-task.js +1 -1
  99. package/dist/routes/test.js +1 -1
  100. package/dist/routes/users.js +1 -1
  101. package/dist/routes/visualizations.js +1 -1
  102. package/dist/scripts/create-user.js +1 -1
  103. package/dist/start.js +1 -1
  104. package/dist/web-ui/public/activity-detail-modal.js +1 -1
  105. package/dist/web-ui/public/activity-feed.js +1 -1
  106. package/dist/web-ui/public/activity-formatters.js +1 -1
  107. package/dist/web-ui/public/agent-event-parser.js +1 -1
  108. package/dist/web-ui/public/app.js +1 -1
  109. package/dist/web-ui/public/approve-dialog.js +1 -1
  110. package/dist/web-ui/public/comments-widget.js +1 -1
  111. package/dist/web-ui/public/diff-utils.js +1 -1
  112. package/dist/web-ui/public/environments.js +1 -1
  113. package/dist/web-ui/public/feedback-widget.css +28 -0
  114. package/dist/web-ui/public/feedback-widget.js +1 -1
  115. package/dist/web-ui/public/git-history-lazy-utils.js +1 -1
  116. package/dist/web-ui/public/git-history.js +1 -1
  117. package/dist/web-ui/public/git-status.js +1 -1
  118. package/dist/web-ui/public/index.js +1 -1
  119. package/dist/web-ui/public/login.js +1 -1
  120. package/dist/web-ui/public/markdown-editor.js +1 -1
  121. package/dist/web-ui/public/markdown-file-editor.js +1 -1
  122. package/dist/web-ui/public/modal-maximize.js +1 -1
  123. package/dist/web-ui/public/notifications.js +1 -1
  124. package/dist/web-ui/public/server-health.js +1 -1
  125. package/dist/web-ui/public/settings.css +134 -44
  126. package/dist/web-ui/public/settings.html +152 -246
  127. package/dist/web-ui/public/settings.js +1 -1
  128. package/dist/web-ui/public/setup-password.js +1 -1
  129. package/dist/web-ui/public/skills.js +1 -1
  130. package/dist/web-ui/public/sse-client.js +1 -1
  131. package/dist/web-ui/public/sse-shared-worker.js +1 -1
  132. package/dist/web-ui/public/styles.css +9 -0
  133. package/dist/web-ui/public/task.js +1 -1
  134. package/dist/web-ui/public/terminal.js +1 -1
  135. package/dist/web-ui/public/theme.js +1 -1
  136. package/dist/web-ui/public/users.js +1 -1
  137. package/dist/web-ui/public/variant-grouping.js +1 -1
  138. package/package.json +1 -1
@@ -138,19 +138,15 @@
138
138
  </svg>
139
139
  Agent Keepalive
140
140
  </button>
141
- <button class="settings-nav-item" data-section="apikeys" role="tab">
141
+ <button class="settings-nav-item" data-section="ai-providers" role="tab">
142
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>
143
+ <path d="M12 3l1.912 5.813a2 2 0 0 0 1.275 1.275L21 12l-5.813 1.912a2 2 0 0 0-1.275 1.275L12 21l-1.912-5.813a2 2 0 0 0-1.275-1.275L3 12l5.813-1.912a2 2 0 0 0 1.275-1.275L12 3z"></path>
144
+ <path d="M5 3v4"></path>
145
+ <path d="M3 5h4"></path>
146
+ <path d="M19 17v4"></path>
147
+ <path d="M17 19h4"></path>
144
148
  </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
149
+ AI Providers
154
150
  </button>
155
151
  <button class="settings-nav-item" data-section="models" role="tab">
156
152
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -306,205 +302,26 @@
306
302
  </div>
307
303
  </div>
308
304
 
309
- <!-- API Keys Settings -->
310
- <div id="section-apikeys" class="settings-panel" role="tabpanel" hidden>
305
+ <!-- AI Providers Settings -->
306
+ <div id="section-ai-providers" class="settings-panel" role="tabpanel" hidden>
311
307
  <div class="content-card">
312
308
  <div class="card-header">
313
- <h3>API Keys</h3>
309
+ <h3>AI Providers</h3>
314
310
  </div>
315
311
  <div class="card-body" style="padding-top: 8px;">
316
- <div id="apikeys-inline-message" class="inline-message" hidden></div>
312
+ <div id="ai-providers-inline-message" class="inline-message" hidden></div>
317
313
  <p class="text-muted" style="margin-bottom: 16px;">
318
- Configure provider API keys and optionally route Claude/Codex/Gemini through custom endpoints (for example Azure Foundry, Azure OpenAI, or gateway proxies).
314
+ Connect OAuth accounts and API key accounts in one place. The active account determines how credentials are injected into tasks.
319
315
  </p>
320
- <div class="apikeys-list">
321
- <!-- Claude (Anthropic) -->
322
- <div class="apikey-row">
323
- <div class="apikey-header">
324
- <span class="apikey-name">Claude</span>
325
- <span class="apikey-provider">Anthropic</span>
326
- </div>
327
- <div class="apikey-controls">
328
- <div class="apikey-input-group">
329
- <input type="password" id="apikey-claude" class="form-input code-font" placeholder="sk-ant-...">
330
- <button type="button" class="btn-icon apikey-toggle-visibility" data-target="apikey-claude" title="Toggle visibility">
331
- <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">
332
- <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
333
- <circle cx="12" cy="12" r="3"></circle>
334
- </svg>
335
- <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;">
336
- <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>
337
- <line x1="1" y1="1" x2="23" y2="23"></line>
338
- </svg>
339
- </button>
340
- </div>
341
- <button type="button" class="btn-secondary btn-small apikey-test-btn" data-agent="claude">Test</button>
342
- <label class="toggle-switch" title="Enable for AI tasks">
343
- <input type="checkbox" id="apikey-claude-enabled">
344
- <span class="toggle-slider"></span>
345
- </label>
346
- </div>
347
- <div class="apikey-endpoint-section" data-agent="claude">
348
- <div class="apikey-endpoint-header">
349
- <span class="apikey-endpoint-label">Custom Endpoint</span>
350
- <label class="toggle-switch" title="Use a custom Claude endpoint">
351
- <input type="checkbox" id="apikey-claude-endpoint-enabled">
352
- <span class="toggle-slider"></span>
353
- </label>
354
- </div>
355
- <div class="apikey-endpoint-fields" id="apikey-claude-endpoint-fields" hidden>
356
- <label class="apikey-endpoint-field-label" for="apikey-claude-base-url">Base URL</label>
357
- <input
358
- type="text"
359
- id="apikey-claude-base-url"
360
- class="form-input code-font"
361
- placeholder="https://your-resource.services.ai.azure.com/anthropic"
362
- >
363
- <span class="form-hint apikey-endpoint-field-hint">
364
- Claude requests will use this base URL when API key task mode is enabled.
365
- </span>
366
- </div>
367
- </div>
368
- </div>
369
-
370
- <!-- Codex (OpenAI) -->
371
- <div class="apikey-row">
372
- <div class="apikey-header">
373
- <span class="apikey-name">Codex</span>
374
- <span class="apikey-provider">OpenAI</span>
375
- </div>
376
- <div class="apikey-controls">
377
- <div class="apikey-input-group">
378
- <input type="password" id="apikey-codex" class="form-input code-font" placeholder="sk-...">
379
- <button type="button" class="btn-icon apikey-toggle-visibility" data-target="apikey-codex" title="Toggle visibility">
380
- <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">
381
- <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
382
- <circle cx="12" cy="12" r="3"></circle>
383
- </svg>
384
- <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;">
385
- <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>
386
- <line x1="1" y1="1" x2="23" y2="23"></line>
387
- </svg>
388
- </button>
389
- </div>
390
- <button type="button" class="btn-secondary btn-small apikey-test-btn" data-agent="codex">Test</button>
391
- <label class="toggle-switch" title="Enable for AI tasks">
392
- <input type="checkbox" id="apikey-codex-enabled">
393
- <span class="toggle-slider"></span>
394
- </label>
395
- </div>
396
- <div class="apikey-endpoint-section" data-agent="codex">
397
- <div class="apikey-endpoint-header">
398
- <span class="apikey-endpoint-label">Custom Endpoint</span>
399
- <label class="toggle-switch" title="Use a custom Codex endpoint">
400
- <input type="checkbox" id="apikey-codex-endpoint-enabled">
401
- <span class="toggle-slider"></span>
402
- </label>
403
- </div>
404
- <div class="apikey-endpoint-fields" id="apikey-codex-endpoint-fields" hidden>
405
- <label class="apikey-endpoint-field-label" for="apikey-codex-base-url">Base URL</label>
406
- <input
407
- type="text"
408
- id="apikey-codex-base-url"
409
- class="form-input code-font"
410
- placeholder="https://your-resource.cognitiveservices.azure.com/openai"
411
- >
412
- <label class="apikey-endpoint-field-label" for="apikey-codex-api-version">API Version (optional)</label>
413
- <input
414
- type="text"
415
- id="apikey-codex-api-version"
416
- class="form-input code-font"
417
- placeholder="2025-04-01-preview"
418
- >
419
- <span class="form-hint apikey-endpoint-field-hint">
420
- Use a root OpenAI base URL. CoderFlow injects <code>api-version</code> as a query parameter when provided.
421
- </span>
422
- </div>
423
- </div>
424
- </div>
425
-
426
- <!-- Gemini (Google) -->
427
- <div class="apikey-row">
428
- <div class="apikey-header">
429
- <span class="apikey-name">Gemini</span>
430
- <span class="apikey-provider">Google</span>
431
- </div>
432
- <div class="apikey-controls">
433
- <div class="apikey-input-group">
434
- <input type="password" id="apikey-gemini" class="form-input code-font" placeholder="AIza...">
435
- <button type="button" class="btn-icon apikey-toggle-visibility" data-target="apikey-gemini" title="Toggle visibility">
436
- <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">
437
- <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
438
- <circle cx="12" cy="12" r="3"></circle>
439
- </svg>
440
- <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;">
441
- <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>
442
- <line x1="1" y1="1" x2="23" y2="23"></line>
443
- </svg>
444
- </button>
445
- </div>
446
- <button type="button" class="btn-secondary btn-small apikey-test-btn" data-agent="gemini">Test</button>
447
- <label class="toggle-switch" title="Enable for AI tasks">
448
- <input type="checkbox" id="apikey-gemini-enabled">
449
- <span class="toggle-slider"></span>
450
- </label>
451
- </div>
452
- <div class="apikey-endpoint-section" data-agent="gemini">
453
- <div class="apikey-endpoint-header">
454
- <span class="apikey-endpoint-label">Custom Endpoint</span>
455
- <label class="toggle-switch" title="Use a custom Gemini endpoint">
456
- <input type="checkbox" id="apikey-gemini-endpoint-enabled">
457
- <span class="toggle-slider"></span>
458
- </label>
459
- </div>
460
- <div class="apikey-endpoint-fields" id="apikey-gemini-endpoint-fields" hidden>
461
- <label class="apikey-endpoint-field-label" for="apikey-gemini-base-url">Base URL</label>
462
- <input
463
- type="text"
464
- id="apikey-gemini-base-url"
465
- class="form-input code-font"
466
- placeholder="https://generativelanguage.googleapis.com/v1beta"
467
- >
468
- <label class="apikey-endpoint-field-label" for="apikey-gemini-api-version">API Version (optional)</label>
469
- <input
470
- type="text"
471
- id="apikey-gemini-api-version"
472
- class="form-input code-font"
473
- placeholder="v1beta"
474
- >
475
- <span class="form-hint apikey-endpoint-field-hint">
476
- You can provide a root Gemini-compatible base URL or a <code>/models</code> path.
477
- </span>
478
- </div>
479
- </div>
480
- </div>
481
- </div>
482
- </div>
483
- <div class="card-actions">
484
- <button type="button" class="btn-primary" id="save-apikeys-btn">Save</button>
485
- </div>
486
- </div>
487
- </div>
488
-
489
- <!-- Provider Authentication Settings -->
490
- <div id="section-provider-auth" class="settings-panel" role="tabpanel" hidden>
491
- <div class="content-card">
492
- <div class="card-header">
493
- <h3>Provider Authentication</h3>
494
- </div>
495
- <div class="card-body" style="padding-top: 8px;">
496
- <div id="provider-auth-inline-message" class="inline-message" hidden></div>
497
- <p class="text-muted" style="margin-bottom: 16px;">Sign in to AI provider accounts. Multiple accounts can be connected per provider.</p>
498
316
 
499
317
  <div class="provider-auth-list">
500
- <!-- Claude (Anthropic) -->
501
318
  <div class="provider-auth-section" data-provider="claude">
502
319
  <div class="provider-auth-header-row">
503
320
  <div class="provider-auth-title">
504
321
  <span class="provider-name">Claude</span>
505
322
  <span class="provider-company">Anthropic</span>
506
323
  </div>
507
- <button class="btn-primary btn-small" id="provider-claude-add-btn">
324
+ <button class="btn-primary btn-small ai-provider-add-btn" id="provider-claude-add-btn">
508
325
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 4px; vertical-align: -1px;">
509
326
  <line x1="12" y1="5" x2="12" y2="19"></line>
510
327
  <line x1="5" y1="12" x2="19" y2="12"></line>
@@ -517,14 +334,13 @@
517
334
  </div>
518
335
  </div>
519
336
 
520
- <!-- Codex (OpenAI) -->
521
337
  <div class="provider-auth-section" data-provider="codex">
522
338
  <div class="provider-auth-header-row">
523
339
  <div class="provider-auth-title">
524
340
  <span class="provider-name">Codex</span>
525
341
  <span class="provider-company">OpenAI</span>
526
342
  </div>
527
- <button class="btn-primary btn-small" id="provider-codex-add-btn">
343
+ <button class="btn-primary btn-small ai-provider-add-btn" id="provider-codex-add-btn">
528
344
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 4px; vertical-align: -1px;">
529
345
  <line x1="12" y1="5" x2="12" y2="19"></line>
530
346
  <line x1="5" y1="12" x2="19" y2="12"></line>
@@ -537,14 +353,13 @@
537
353
  </div>
538
354
  </div>
539
355
 
540
- <!-- Gemini (Google) -->
541
356
  <div class="provider-auth-section" data-provider="gemini">
542
357
  <div class="provider-auth-header-row">
543
358
  <div class="provider-auth-title">
544
359
  <span class="provider-name">Gemini</span>
545
360
  <span class="provider-company">Google</span>
546
361
  </div>
547
- <button class="btn-primary btn-small" id="provider-gemini-add-btn">
362
+ <button class="btn-primary btn-small ai-provider-add-btn" id="provider-gemini-add-btn">
548
363
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 4px; vertical-align: -1px;">
549
364
  <line x1="12" y1="5" x2="12" y2="19"></line>
550
365
  <line x1="5" y1="12" x2="19" y2="12"></line>
@@ -893,71 +708,162 @@
893
708
  </div>
894
709
  </main>
895
710
 
896
- <!-- Provider Sign-In Flow Modal -->
897
- <div id="provider-signin-modal" class="modal" hidden>
711
+ <!-- AI Provider Add Account Modal -->
712
+ <div id="ai-provider-add-modal" class="modal" hidden>
898
713
  <div class="modal-overlay"></div>
899
714
  <div class="modal-content">
900
715
  <div class="modal-header">
901
- <h2 id="provider-signin-title">Sign in with Provider</h2>
716
+ <h2 id="ai-provider-add-title">Add Account</h2>
902
717
  <button type="button" class="modal-close" aria-label="Close">&times;</button>
903
718
  </div>
904
719
  <div class="modal-body">
905
- <div class="signin-steps">
906
- <div class="signin-step">
907
- <span class="step-number">1</span>
908
- <span class="step-text">Open the secure sign-in page</span>
909
- </div>
910
- <button class="btn-primary" id="provider-signin-open-btn" style="width: 100%; margin: 8px 0 16px 0;">
911
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 8px; vertical-align: -2px;">
912
- <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
913
- <polyline points="15 3 21 3 21 9"></polyline>
914
- <line x1="10" y1="14" x2="21" y2="3"></line>
915
- </svg>
916
- Open Sign-In Page
917
- </button>
918
-
919
- <div class="signin-step">
920
- <span class="step-number">2</span>
921
- <span class="step-text" id="provider-signin-instructions">
922
- Complete sign-in and copy the authorization code
923
- </span>
924
- </div>
720
+ <div class="ai-provider-add-tabs">
721
+ <button type="button" class="ai-provider-tab active" data-tab="oauth">OAuth Sign-In</button>
722
+ <button type="button" class="ai-provider-tab" data-tab="api-key">API Key</button>
723
+ </div>
925
724
 
926
- <!-- Secure redirect notice for URL-copy flow (Codex/Gemini) -->
927
- <div id="provider-signin-localhost-notice" class="secure-redirect-notice" hidden>
928
- <div class="secure-redirect-header">
929
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
930
- <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
931
- <path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
725
+ <div id="ai-provider-tab-oauth" class="ai-provider-tab-content active">
726
+ <div class="signin-steps">
727
+ <div class="signin-step">
728
+ <span class="step-number">1</span>
729
+ <span class="step-text">Open the secure sign-in page</span>
730
+ </div>
731
+ <button class="btn-primary" id="provider-signin-open-btn" style="width: 100%; margin: 8px 0 16px 0;">
732
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 8px; vertical-align: -2px;">
733
+ <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
734
+ <polyline points="15 3 21 3 21 9"></polyline>
735
+ <line x1="10" y1="14" x2="21" y2="3"></line>
932
736
  </svg>
933
- <span>Secure Local Redirect</span>
737
+ Open Sign-In Page
738
+ </button>
739
+
740
+ <div class="signin-step">
741
+ <span class="step-number">2</span>
742
+ <span class="step-text" id="provider-signin-instructions">
743
+ Complete sign-in and copy the authorization code
744
+ </span>
745
+ </div>
746
+
747
+ <div id="provider-signin-localhost-notice" class="secure-redirect-notice" hidden>
748
+ <div class="secure-redirect-header">
749
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
750
+ <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
751
+ <path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
752
+ </svg>
753
+ <span>Secure Local Redirect</span>
754
+ </div>
755
+ <p>After signing in, your browser will redirect to a local address. The page won't load; this is expected. Copy the full URL from your browser address bar.</p>
756
+ </div>
757
+
758
+ <div class="form-row" style="margin-top: 12px; grid-template-columns: auto 1fr; gap: 8px;">
759
+ <label for="provider-signin-input" id="provider-signin-label">Authorization Code or URL</label>
760
+ <input type="text" id="provider-signin-input" class="form-input code-font" placeholder="Paste code or URL here">
761
+ </div>
762
+
763
+ <div class="signin-step" style="margin-top: 16px;">
764
+ <span class="step-number">3</span>
765
+ <span class="step-text">Name this account</span>
934
766
  </div>
935
- <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>
936
- <div class="secure-redirect-instruction">
937
- <strong>Copy the complete URL</strong> from your browser's address bar and paste it below.
767
+ <div class="form-row" style="margin-top: 8px; grid-template-columns: auto 1fr; gap: 8px;">
768
+ <label for="provider-signin-label-input">Account Label</label>
769
+ <input type="text" id="provider-signin-label-input" class="form-input" placeholder="e.g., Production, Team Account">
938
770
  </div>
939
771
  </div>
772
+ </div>
940
773
 
941
- <div class="form-row" style="margin-top: 12px; grid-template-columns: auto 1fr; gap: 8px;">
942
- <label for="provider-signin-input" id="provider-signin-label">Authorization Code or URL</label>
943
- <input type="text" id="provider-signin-input" class="form-input code-font"
944
- placeholder="Paste code or URL here">
774
+ <div id="ai-provider-tab-api-key" class="ai-provider-tab-content">
775
+ <div class="form-single-column" style="max-width: 100%;">
776
+ <div class="form-row">
777
+ <label for="ai-provider-api-key-label">Account Label</label>
778
+ <input type="text" id="ai-provider-api-key-label" class="form-input" placeholder="e.g., Production Key">
779
+ </div>
780
+ <div class="form-row">
781
+ <label for="ai-provider-api-key-input">API Key</label>
782
+ <div class="apikey-input-group">
783
+ <input type="password" id="ai-provider-api-key-input" class="form-input code-font" placeholder="Paste API key">
784
+ <button type="button" class="btn-icon apikey-toggle-visibility" data-target="ai-provider-api-key-input" title="Toggle visibility">
785
+ <svg class="eye-open" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
786
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
787
+ <circle cx="12" cy="12" r="3"></circle>
788
+ </svg>
789
+ <svg class="eye-closed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display: none;">
790
+ <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>
791
+ <line x1="1" y1="1" x2="23" y2="23"></line>
792
+ </svg>
793
+ </button>
794
+ </div>
795
+ </div>
796
+ <div class="form-row">
797
+ <label for="ai-provider-api-key-endpoint-enabled">Custom Endpoint</label>
798
+ <label class="toggle-switch">
799
+ <input type="checkbox" id="ai-provider-api-key-endpoint-enabled">
800
+ <span class="toggle-slider"></span>
801
+ </label>
802
+ </div>
803
+ <div id="ai-provider-api-key-endpoint-fields" class="apikey-endpoint-fields" hidden>
804
+ <label class="apikey-endpoint-field-label" for="ai-provider-api-key-base-url">Base URL</label>
805
+ <input type="text" id="ai-provider-api-key-base-url" class="form-input code-font" placeholder="https://your-endpoint.example.com">
806
+ <label class="apikey-endpoint-field-label" for="ai-provider-api-key-api-version">API Version (optional)</label>
807
+ <input type="text" id="ai-provider-api-key-api-version" class="form-input code-font" placeholder="2025-04-01-preview">
808
+ </div>
945
809
  </div>
810
+ </div>
811
+ </div>
812
+ <div class="modal-actions">
813
+ <button type="button" class="btn-secondary" id="ai-provider-add-cancel-btn">Cancel</button>
814
+ <button type="button" class="btn-primary" id="ai-provider-add-submit-btn">Complete Sign-In</button>
815
+ </div>
816
+ </div>
817
+ </div>
946
818
 
947
- <div class="signin-step" style="margin-top: 16px;">
948
- <span class="step-number">3</span>
949
- <span class="step-text">Name this account</span>
819
+ <!-- Edit API Key Modal -->
820
+ <div id="ai-provider-edit-api-key-modal" class="modal" hidden>
821
+ <div class="modal-overlay"></div>
822
+ <div class="modal-content">
823
+ <div class="modal-header">
824
+ <h2>Edit API Key Account</h2>
825
+ <button type="button" class="modal-close" aria-label="Close">&times;</button>
826
+ </div>
827
+ <div class="modal-body">
828
+ <div class="form-single-column" style="max-width: 100%;">
829
+ <div class="form-row">
830
+ <label for="ai-provider-edit-label">Account Label</label>
831
+ <input type="text" id="ai-provider-edit-label" class="form-input" placeholder="e.g., Production Key">
832
+ </div>
833
+ <div class="form-row">
834
+ <label for="ai-provider-edit-api-key">API Key</label>
835
+ <div class="apikey-input-group">
836
+ <input type="password" id="ai-provider-edit-api-key" class="form-input code-font" placeholder="Leave blank to keep existing">
837
+ <button type="button" class="btn-icon apikey-toggle-visibility" data-target="ai-provider-edit-api-key" title="Toggle visibility">
838
+ <svg class="eye-open" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
839
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
840
+ <circle cx="12" cy="12" r="3"></circle>
841
+ </svg>
842
+ <svg class="eye-closed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display: none;">
843
+ <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>
844
+ <line x1="1" y1="1" x2="23" y2="23"></line>
845
+ </svg>
846
+ </button>
847
+ </div>
848
+ </div>
849
+ <div class="form-row">
850
+ <label for="ai-provider-edit-endpoint-enabled">Custom Endpoint</label>
851
+ <label class="toggle-switch">
852
+ <input type="checkbox" id="ai-provider-edit-endpoint-enabled">
853
+ <span class="toggle-slider"></span>
854
+ </label>
950
855
  </div>
951
- <div class="form-row" style="margin-top: 8px; grid-template-columns: auto 1fr; gap: 8px;">
952
- <label for="provider-signin-label-input">Account Label</label>
953
- <input type="text" id="provider-signin-label-input" class="form-input"
954
- placeholder="e.g., Production, Development, Team">
856
+ <div id="ai-provider-edit-endpoint-fields" class="apikey-endpoint-fields" hidden>
857
+ <label class="apikey-endpoint-field-label" for="ai-provider-edit-base-url">Base URL</label>
858
+ <input type="text" id="ai-provider-edit-base-url" class="form-input code-font" placeholder="https://your-endpoint.example.com">
859
+ <label class="apikey-endpoint-field-label" for="ai-provider-edit-api-version">API Version (optional)</label>
860
+ <input type="text" id="ai-provider-edit-api-version" class="form-input code-font" placeholder="2025-04-01-preview">
955
861
  </div>
956
862
  </div>
957
863
  </div>
958
864
  <div class="modal-actions">
959
- <button type="button" class="btn-secondary" id="provider-signin-cancel-btn">Cancel</button>
960
- <button type="button" class="btn-primary" id="provider-signin-submit-btn">Complete Sign-In</button>
865
+ <button type="button" class="btn-secondary" id="ai-provider-edit-cancel-btn">Cancel</button>
866
+ <button type="button" class="btn-primary" id="ai-provider-edit-save-btn">Save</button>
961
867
  </div>
962
868
  </div>
963
869
  </div>