@kervnet/opencode-kiro-auth 1.5.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 (106) hide show
  1. package/README.md +159 -0
  2. package/dist/constants.d.ts +24 -0
  3. package/dist/constants.js +55 -0
  4. package/dist/core/account/account-selector.d.ts +25 -0
  5. package/dist/core/account/account-selector.js +84 -0
  6. package/dist/core/account/usage-tracker.d.ts +17 -0
  7. package/dist/core/account/usage-tracker.js +39 -0
  8. package/dist/core/auth/auth-handler.d.ts +15 -0
  9. package/dist/core/auth/auth-handler.js +43 -0
  10. package/dist/core/auth/idc-auth-method.d.ts +17 -0
  11. package/dist/core/auth/idc-auth-method.js +200 -0
  12. package/dist/core/auth/token-refresher.d.ts +22 -0
  13. package/dist/core/auth/token-refresher.js +53 -0
  14. package/dist/core/index.d.ts +9 -0
  15. package/dist/core/index.js +9 -0
  16. package/dist/core/request/error-handler.d.ts +30 -0
  17. package/dist/core/request/error-handler.js +113 -0
  18. package/dist/core/request/request-handler.d.ts +27 -0
  19. package/dist/core/request/request-handler.js +199 -0
  20. package/dist/core/request/response-handler.d.ts +5 -0
  21. package/dist/core/request/response-handler.js +61 -0
  22. package/dist/core/request/retry-strategy.d.ts +18 -0
  23. package/dist/core/request/retry-strategy.js +28 -0
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.js +1 -0
  26. package/dist/infrastructure/database/account-cache.d.ts +14 -0
  27. package/dist/infrastructure/database/account-cache.js +44 -0
  28. package/dist/infrastructure/database/account-repository.d.ts +12 -0
  29. package/dist/infrastructure/database/account-repository.js +64 -0
  30. package/dist/infrastructure/index.d.ts +7 -0
  31. package/dist/infrastructure/index.js +7 -0
  32. package/dist/infrastructure/transformers/event-stream-parser.d.ts +7 -0
  33. package/dist/infrastructure/transformers/event-stream-parser.js +115 -0
  34. package/dist/infrastructure/transformers/history-builder.d.ts +5 -0
  35. package/dist/infrastructure/transformers/history-builder.js +171 -0
  36. package/dist/infrastructure/transformers/message-transformer.d.ts +6 -0
  37. package/dist/infrastructure/transformers/message-transformer.js +102 -0
  38. package/dist/infrastructure/transformers/tool-call-parser.d.ts +4 -0
  39. package/dist/infrastructure/transformers/tool-call-parser.js +45 -0
  40. package/dist/infrastructure/transformers/tool-transformer.d.ts +2 -0
  41. package/dist/infrastructure/transformers/tool-transformer.js +19 -0
  42. package/dist/kiro/auth.d.ts +4 -0
  43. package/dist/kiro/auth.js +25 -0
  44. package/dist/kiro/oauth-idc.d.ts +24 -0
  45. package/dist/kiro/oauth-idc.js +151 -0
  46. package/dist/plugin/accounts.d.ts +29 -0
  47. package/dist/plugin/accounts.js +235 -0
  48. package/dist/plugin/auth-page.d.ts +3 -0
  49. package/dist/plugin/auth-page.js +573 -0
  50. package/dist/plugin/cli.d.ts +8 -0
  51. package/dist/plugin/cli.js +103 -0
  52. package/dist/plugin/config/index.d.ts +3 -0
  53. package/dist/plugin/config/index.js +2 -0
  54. package/dist/plugin/config/loader.d.ts +6 -0
  55. package/dist/plugin/config/loader.js +129 -0
  56. package/dist/plugin/config/schema.d.ts +56 -0
  57. package/dist/plugin/config/schema.js +36 -0
  58. package/dist/plugin/errors.d.ts +17 -0
  59. package/dist/plugin/errors.js +34 -0
  60. package/dist/plugin/health.d.ts +1 -0
  61. package/dist/plugin/health.js +9 -0
  62. package/dist/plugin/image-handler.d.ts +14 -0
  63. package/dist/plugin/image-handler.js +64 -0
  64. package/dist/plugin/logger.d.ts +8 -0
  65. package/dist/plugin/logger.js +63 -0
  66. package/dist/plugin/models.d.ts +1 -0
  67. package/dist/plugin/models.js +8 -0
  68. package/dist/plugin/request.d.ts +2 -0
  69. package/dist/plugin/request.js +239 -0
  70. package/dist/plugin/response.d.ts +3 -0
  71. package/dist/plugin/response.js +95 -0
  72. package/dist/plugin/server.d.ts +24 -0
  73. package/dist/plugin/server.js +166 -0
  74. package/dist/plugin/storage/locked-operations.d.ts +5 -0
  75. package/dist/plugin/storage/locked-operations.js +91 -0
  76. package/dist/plugin/storage/migrations.d.ts +2 -0
  77. package/dist/plugin/storage/migrations.js +109 -0
  78. package/dist/plugin/storage/sqlite.d.ts +17 -0
  79. package/dist/plugin/storage/sqlite.js +134 -0
  80. package/dist/plugin/streaming/index.d.ts +2 -0
  81. package/dist/plugin/streaming/index.js +2 -0
  82. package/dist/plugin/streaming/openai-converter.d.ts +2 -0
  83. package/dist/plugin/streaming/openai-converter.js +68 -0
  84. package/dist/plugin/streaming/stream-parser.d.ts +5 -0
  85. package/dist/plugin/streaming/stream-parser.js +136 -0
  86. package/dist/plugin/streaming/stream-state.d.ts +5 -0
  87. package/dist/plugin/streaming/stream-state.js +59 -0
  88. package/dist/plugin/streaming/stream-transformer.d.ts +1 -0
  89. package/dist/plugin/streaming/stream-transformer.js +248 -0
  90. package/dist/plugin/streaming/types.d.ts +25 -0
  91. package/dist/plugin/streaming/types.js +2 -0
  92. package/dist/plugin/sync/aws-sso.d.ts +2 -0
  93. package/dist/plugin/sync/aws-sso.js +50 -0
  94. package/dist/plugin/sync/kiro-cli-parser.d.ts +8 -0
  95. package/dist/plugin/sync/kiro-cli-parser.js +72 -0
  96. package/dist/plugin/sync/kiro-cli.d.ts +2 -0
  97. package/dist/plugin/sync/kiro-cli.js +197 -0
  98. package/dist/plugin/token.d.ts +2 -0
  99. package/dist/plugin/token.js +79 -0
  100. package/dist/plugin/types.d.ts +109 -0
  101. package/dist/plugin/types.js +0 -0
  102. package/dist/plugin/usage.d.ts +3 -0
  103. package/dist/plugin/usage.js +45 -0
  104. package/dist/plugin.d.ts +32 -0
  105. package/dist/plugin.js +37 -0
  106. package/package.json +65 -0
@@ -0,0 +1,573 @@
1
+ function escapeHtml(text) {
2
+ return text
3
+ .replace(/&/g, '&')
4
+ .replace(/</g, '&lt;')
5
+ .replace(/>/g, '&gt;')
6
+ .replace(/"/g, '&quot;')
7
+ .replace(/'/g, '&#039;');
8
+ }
9
+ export function getIDCAuthHtml(verificationUrl, userCode, statusUrl) {
10
+ const escapedUrl = escapeHtml(verificationUrl);
11
+ const escapedCode = escapeHtml(userCode);
12
+ const escapedStatusUrl = escapeHtml(statusUrl);
13
+ return `<!DOCTYPE html>
14
+ <html lang="en">
15
+ <head>
16
+ <meta charset="UTF-8">
17
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
18
+ <title>AWS Builder ID Authentication</title>
19
+ <style>
20
+ * {
21
+ margin: 0;
22
+ padding: 0;
23
+ box-sizing: border-box;
24
+ }
25
+ body {
26
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
27
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
28
+ min-height: 100vh;
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ padding: 20px;
33
+ }
34
+ .container {
35
+ background: white;
36
+ border-radius: 16px;
37
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
38
+ max-width: 500px;
39
+ width: 100%;
40
+ padding: 48px 40px;
41
+ text-align: center;
42
+ animation: slideIn 0.4s ease-out;
43
+ }
44
+ @keyframes slideIn {
45
+ from {
46
+ opacity: 0;
47
+ transform: translateY(-20px);
48
+ }
49
+ to {
50
+ opacity: 1;
51
+ transform: translateY(0);
52
+ }
53
+ }
54
+ h1 {
55
+ color: #1a202c;
56
+ font-size: 28px;
57
+ font-weight: 700;
58
+ margin-bottom: 12px;
59
+ }
60
+ .subtitle {
61
+ color: #718096;
62
+ font-size: 16px;
63
+ margin-bottom: 32px;
64
+ line-height: 1.5;
65
+ }
66
+ .code-container {
67
+ background: #f7fafc;
68
+ border: 2px solid #e2e8f0;
69
+ border-radius: 12px;
70
+ padding: 24px;
71
+ margin-bottom: 24px;
72
+ position: relative;
73
+ }
74
+ .code-label {
75
+ color: #4a5568;
76
+ font-size: 14px;
77
+ font-weight: 600;
78
+ text-transform: uppercase;
79
+ letter-spacing: 0.5px;
80
+ margin-bottom: 12px;
81
+ }
82
+ .code {
83
+ font-family: 'Courier New', monospace;
84
+ font-size: 32px;
85
+ font-weight: 700;
86
+ color: #2d3748;
87
+ letter-spacing: 4px;
88
+ user-select: all;
89
+ cursor: pointer;
90
+ padding: 8px;
91
+ border-radius: 6px;
92
+ transition: background 0.2s;
93
+ }
94
+ .code:hover {
95
+ background: #edf2f7;
96
+ }
97
+ .copy-hint {
98
+ color: #a0aec0;
99
+ font-size: 12px;
100
+ margin-top: 8px;
101
+ }
102
+ .url-container {
103
+ margin-bottom: 32px;
104
+ }
105
+ .url-label {
106
+ color: #4a5568;
107
+ font-size: 14px;
108
+ font-weight: 600;
109
+ margin-bottom: 12px;
110
+ }
111
+ .url-link {
112
+ display: inline-block;
113
+ color: #4299e1;
114
+ text-decoration: none;
115
+ font-size: 16px;
116
+ padding: 12px 24px;
117
+ border: 2px solid #4299e1;
118
+ border-radius: 8px;
119
+ transition: all 0.2s;
120
+ font-weight: 600;
121
+ }
122
+ .url-link:hover {
123
+ background: #4299e1;
124
+ color: white;
125
+ transform: translateY(-2px);
126
+ box-shadow: 0 4px 12px rgba(66, 153, 225, 0.4);
127
+ }
128
+ .status {
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: center;
132
+ gap: 12px;
133
+ color: #718096;
134
+ font-size: 14px;
135
+ margin-top: 32px;
136
+ padding-top: 24px;
137
+ border-top: 1px solid #e2e8f0;
138
+ }
139
+ .spinner {
140
+ width: 20px;
141
+ height: 20px;
142
+ border: 3px solid #e2e8f0;
143
+ border-top-color: #4299e1;
144
+ border-radius: 50%;
145
+ animation: spin 0.8s linear infinite;
146
+ }
147
+ @keyframes spin {
148
+ to { transform: rotate(360deg); }
149
+ }
150
+ .instructions {
151
+ background: #edf2f7;
152
+ border-radius: 8px;
153
+ padding: 16px;
154
+ margin-bottom: 24px;
155
+ text-align: left;
156
+ }
157
+ .instructions ol {
158
+ margin-left: 20px;
159
+ color: #4a5568;
160
+ font-size: 14px;
161
+ line-height: 1.8;
162
+ }
163
+ .instructions li {
164
+ margin-bottom: 8px;
165
+ }
166
+ @media (max-width: 600px) {
167
+ .container {
168
+ padding: 32px 24px;
169
+ }
170
+ h1 {
171
+ font-size: 24px;
172
+ }
173
+ .code {
174
+ font-size: 24px;
175
+ letter-spacing: 2px;
176
+ }
177
+ }
178
+ </style>
179
+ </head>
180
+ <body>
181
+ <div class="container">
182
+ <h1>AWS Builder ID Authentication</h1>
183
+ <p class="subtitle">Complete the authentication in your browser</p>
184
+
185
+ <div class="instructions">
186
+ <ol>
187
+ <li>A browser window will open automatically</li>
188
+ <li>Enter the code shown below</li>
189
+ <li>Complete the authentication process</li>
190
+ </ol>
191
+ </div>
192
+
193
+ <div class="code-container">
194
+ <div class="code-label">Your Code</div>
195
+ <div class="code" onclick="copyCode()">${escapedCode}</div>
196
+ <div class="copy-hint">Click to copy</div>
197
+ </div>
198
+
199
+ <div class="url-container">
200
+ <div class="url-label">Verification URL</div>
201
+ <a href="${escapedUrl}" target="_blank" class="url-link">Open Browser</a>
202
+ </div>
203
+
204
+ <div class="status">
205
+ <div class="spinner"></div>
206
+ <span>Waiting for authentication...</span>
207
+ </div>
208
+ </div>
209
+
210
+ <script>
211
+ const statusUrl = '${escapedStatusUrl}';
212
+ const verificationUrl = '${escapedUrl}';
213
+
214
+ function copyCode() {
215
+ const code = '${escapedCode}';
216
+ navigator.clipboard.writeText(code).then(() => {
217
+ const codeEl = document.querySelector('.code');
218
+ const originalBg = codeEl.style.background;
219
+ codeEl.style.background = '#48bb78';
220
+ codeEl.style.color = 'white';
221
+ setTimeout(() => {
222
+ codeEl.style.background = originalBg;
223
+ codeEl.style.color = '#2d3748';
224
+ }, 300);
225
+ }).catch(() => {});
226
+ }
227
+
228
+ window.addEventListener('load', () => {
229
+ setTimeout(() => {
230
+ window.open(verificationUrl, '_blank');
231
+ }, 500);
232
+ });
233
+
234
+ async function checkStatus() {
235
+ try {
236
+ const response = await fetch(statusUrl);
237
+ const data = await response.json();
238
+
239
+ if (data.status === 'success') {
240
+ window.location.href = '/success';
241
+ } else if (data.status === 'failed' || data.status === 'timeout') {
242
+ window.location.href = '/error?message=' + encodeURIComponent(data.message || 'Authentication failed');
243
+ }
244
+ } catch (error) {
245
+ console.error('Status check failed:', error);
246
+ }
247
+ }
248
+
249
+ setInterval(checkStatus, 2000);
250
+ checkStatus();
251
+ </script>
252
+ </body>
253
+ </html>`;
254
+ }
255
+ export function getSuccessHtml() {
256
+ return `<!DOCTYPE html>
257
+ <html lang="en">
258
+ <head>
259
+ <meta charset="UTF-8">
260
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
261
+ <title>Authentication Successful</title>
262
+ <style>
263
+ * {
264
+ margin: 0;
265
+ padding: 0;
266
+ box-sizing: border-box;
267
+ }
268
+ body {
269
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
270
+ background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
271
+ min-height: 100vh;
272
+ display: flex;
273
+ align-items: center;
274
+ justify-content: center;
275
+ padding: 20px;
276
+ }
277
+ .container {
278
+ background: white;
279
+ border-radius: 16px;
280
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
281
+ max-width: 450px;
282
+ width: 100%;
283
+ padding: 48px 40px;
284
+ text-align: center;
285
+ animation: slideIn 0.4s ease-out;
286
+ }
287
+ @keyframes slideIn {
288
+ from {
289
+ opacity: 0;
290
+ transform: scale(0.9);
291
+ }
292
+ to {
293
+ opacity: 1;
294
+ transform: scale(1);
295
+ }
296
+ }
297
+ .checkmark {
298
+ width: 80px;
299
+ height: 80px;
300
+ margin: 0 auto 24px;
301
+ position: relative;
302
+ }
303
+ .checkmarkcle {
304
+ width: 80px;
305
+ height: 80px;
306
+ border-radius: 50%;
307
+ background: #48bb78;
308
+ animation: scaleIn 0.5s ease-out;
309
+ }
310
+ @keyframes scaleIn {
311
+ from {
312
+ transform: scale(0);
313
+ }
314
+ to {
315
+ transform: scale(1);
316
+ }
317
+ }
318
+ .checkmark-check {
319
+ position: absolute;
320
+ top: 50%;
321
+ left: 50%;
322
+ transform: translate(-50%, -50%);
323
+ width: 30px;
324
+ height: 50px;
325
+ border: solid white;
326
+ border-width: 0 6px 6px 0;
327
+ transform: translate(-50%, -60%) rotate(45deg);
328
+ animation: checkmark 0.5s 0.3s ease-out forwards;
329
+ opacity: 0;
330
+ }
331
+ @keyframes checkmark {
332
+ to {
333
+ opacity: 1;
334
+ transform: translate(-50%, -60%) rotate(45deg) scale(1);
335
+ }
336
+ }
337
+ h1 {
338
+ color: #1a202c;
339
+ font-size: 28px;
340
+ font-weight: 700;
341
+ margin-bottom: 12px;
342
+ }
343
+ .message {
344
+ color: #718096;
345
+ font-size: 16px;
346
+ line-height: 1.6;
347
+ margin-bottom: 24px;
348
+ }
349
+ .auto-close {
350
+ color: #a0aec0;
351
+ font-size: 14px;
352
+ padding-top: 24px;
353
+ border-top: 1px solid #e2e8f0;
354
+ }
355
+ @media (max-width: 600px) {
356
+ .container {
357
+ padding: 32px 24px;
358
+ }
359
+ h1 {
360
+ font-size: 24px;
361
+ }
362
+ }
363
+ </style>
364
+ </head>
365
+ <body>
366
+ <div class="container">
367
+ <div class="checkmark">
368
+ <div class="checkmark-circle"></div>
369
+ <div class="checkmark-check"></div>
370
+ </div>
371
+ <h1>Authentication Successful!</h1>
372
+ <p class="message">You have been successfully authenticated with AWS Builder ID. You can now close this window and return to your terminal.</p>
373
+ <div class="auto-close">This window will close automatically in <span id="countdown">3</span> seconds</div>
374
+ </div>
375
+
376
+ <script>
377
+ let seconds = 3;
378
+ const countdownEl = document.getElementById('countdown');
379
+
380
+ const interval = setInterval(() => {
381
+ seconds--;
382
+ if (countdownEl) {
383
+ countdownEl.textContent = seconds.toString();
384
+ }
385
+
386
+ if (seconds <= 0) {
387
+ clearInterval(interval);
388
+ try {
389
+ window.close();
390
+ } catch (e) {
391
+ console.log('Couluto-close window');
392
+ }
393
+ }
394
+ }, 1000);
395
+ </script>
396
+ </body>
397
+ </html>`;
398
+ }
399
+ export function getErrorHtml(message) {
400
+ const escapedMessage = escapeHtml(message);
401
+ return `<!DOCTYPE html>
402
+ <html lang="en">
403
+ <head>
404
+ <meta charset="UTF-8">
405
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
406
+ <title>Authentication Failed</title>
407
+ <style>
408
+ * {
409
+ margin: 0;
410
+ padding: 0;
411
+ box-sizing: border-box;
412
+ }
413
+ body {
414
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
415
+ background: linear-gradient(135deg, #fc8181 0%, #f56565 100%);
416
+ min-height: 100vh;
417
+ display: flex;
418
+ align-items: center;
419
+ justify-content: center;
420
+ padding: 20px;
421
+ }
422
+ .container {
423
+ background: white;
424
+ border-radius: 16px;
425
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
426
+ max-width: 450px;
427
+ width: 100%;
428
+ padding: 48px 40px;
429
+ text-align: center;
430
+ animation: slideIn 0.4s ease-out;
431
+ }
432
+ @keyframes slideIn {
433
+ from {
434
+ opacity: 0;
435
+ transform: scale(0.9);
436
+ }
437
+ to {
438
+ opacity: 1;
439
+ transform: scale(1);
440
+ }
441
+ }
442
+ .error-icon {
443
+ width: 80px;
444
+ height: 80px;
445
+ margin: 0 auto 24px;
446
+ position: relative;
447
+ }
448
+ .error-circle {
449
+ width: 80px;
450
+ height: 80px;
451
+ border-radius: 50%;
452
+ background: #fc8181;
453
+ animation: scaleIn 0.5s ease-out;
454
+ }
455
+ @keyframes scaleIn {
456
+ from {
457
+ transform: scale(0);
458
+ }
459
+ to {
460
+ transform: scale(1);
461
+ }
462
+ }
463
+ .error-x {
464
+ position: absolute;
465
+ top: 50%;
466
+ left: 50%;
467
+ transform: translate(-50%, -50%);
468
+ width: 40px;
469
+ height: 40px;
470
+ }
471
+ .error-x::before,
472
+ .error-x::after {
473
+ content: '';
474
+ position: absolute;
475
+ top: 50%;
476
+ left: 50%;
477
+ width: 40px;
478
+ height: 6px;
479
+ background: white;
480
+ border-radius: 3px;
481
+ animation: xmark 0.5s 0.3s ease-out forwards;
482
+ opacity: 0;
483
+ }
484
+ .error-x::before {
485
+ transform: translate(-50%, -50%) rotate(45deg);
486
+ }
487
+ .error-x::after {
488
+ transform: translate(-50%, -50%) rotate(-45deg);
489
+ }
490
+ @keyframes xmark {
491
+ to {
492
+ opacity: 1;
493
+ }
494
+ }
495
+ h1 {
496
+ color: #1a202c;
497
+ font-size: 28px;
498
+ font-weight: 700;
499
+ margin-bottom: 12px;
500
+ }
501
+ .message {
502
+ color: #718096;
503
+ font-size: 16px;
504
+ line-height: 1.6;
505
+ margin-bottom: 16px;
506
+ }
507
+ .error-details {
508
+ background: #fff5f5;
509
+ border: 1px solid #feb2b2;
510
+ border-radius: 8px;
511
+ padding: 16px;
512
+ margin-bottom: 24px;
513
+ color: #c53030;
514
+ font-size: 14px;
515
+ word-break: break-word;
516
+ }
517
+ .instruction {
518
+ color: #4a5568;
519
+ font-size: 15px;
520
+ margin-bottom: 24px;
521
+ }
522
+ .auto-close {
523
+ color: #a0aec0;
524
+ font-size: 14px;
525
+ padding-top: 24px;
526
+ border-top: 1px solid #e2e8f0;
527
+ }
528
+ @media (max-width: 600px) {
529
+ .container {
530
+ padding: 32px 24px;
531
+ }
532
+ h1 {
533
+ font-size: 24px;
534
+ }
535
+ }
536
+ </style>
537
+ </head>
538
+ <body>
539
+ <div class="container">
540
+ <div class="error-icon">
541
+ <div class="error-circle"></div>
542
+ <div class="error-x"></div>
543
+ </div>
544
+ <h1>Authentication Failed</h1>
545
+ <p class="message">We were unable to complete the authentication process.</p>
546
+ <div class="error-details">${escapedMessage}</div>
547
+ <p class="instruction">You can close this window and try again from your terminal.</p>
548
+ <div class="auto-close">This window will close automatically in <span id="countdown">5</span> seconds</div>
549
+ </div>
550
+
551
+ <script>
552
+ let seconds = 5;
553
+ const countdownEl = document.getElementById('countdown');
554
+
555
+ const interval = setInterval(() => {
556
+ seconds--;
557
+ if (countdownEl) {
558
+ countdownEl.textContent = seconds.toString();
559
+ }
560
+
561
+ if (seconds <= 0) {
562
+ clearInterval(interval);
563
+ try {
564
+ window.close();
565
+ } catch (e) {
566
+ console.log('Could not auto-close window');
567
+ }
568
+ }
569
+ }, 1000);
570
+ </script>
571
+ </body>
572
+ </html>`;
573
+ }
@@ -0,0 +1,8 @@
1
+ export declare function promptAddAnotherAccount(currentCount: number): Promise<boolean>;
2
+ export declare function promptDeleteAccount(accounts: ExistingAccountInfo[]): Promise<number[] | null>;
3
+ export type LoginMode = 'add' | 'fresh' | 'delete';
4
+ export interface ExistingAccountInfo {
5
+ email?: string;
6
+ index: number;
7
+ }
8
+ export declare function promptLoginMode(existingAccounts: ExistingAccountInfo[]): Promise<LoginMode>;
@@ -0,0 +1,103 @@
1
+ import { stdin as input, stdout as output } from 'node:process';
2
+ import { createInterface } from 'node:readline/promises';
3
+ export async function promptAddAnotherAccount(currentCount) {
4
+ const rl = createInterface({ input, output });
5
+ try {
6
+ const answer = await rl.question(`Add another account? (${currentCount} added) (y/n): `);
7
+ const normalized = answer.trim().toLowerCase();
8
+ return normalized === 'y' || normalized === 'yes';
9
+ }
10
+ finally {
11
+ rl.close();
12
+ }
13
+ }
14
+ export async function promptDeleteAccount(accounts) {
15
+ const rl = createInterface({ input, output });
16
+ try {
17
+ console.log(`\nSelect account(s) to delete:`);
18
+ for (const acc of accounts) {
19
+ const label = acc.email || `Account ${acc.index + 1}`;
20
+ console.log(` ${acc.index + 1}. ${label}`);
21
+ }
22
+ console.log(` 0. Cancel`);
23
+ console.log('');
24
+ while (true) {
25
+ const answer = await rl.question('Enter account number(s) (e.g., 1,2,3 or 1): ');
26
+ const trimmed = answer.trim();
27
+ if (trimmed === '0') {
28
+ return null;
29
+ }
30
+ const parts = trimmed.split(',').map((s) => s.trim());
31
+ const numbers = [];
32
+ let invalid = false;
33
+ for (const part of parts) {
34
+ const num = parseInt(part, 10);
35
+ if (isNaN(num) || num < 1 || num > accounts.length) {
36
+ invalid = true;
37
+ break;
38
+ }
39
+ if (!numbers.includes(num)) {
40
+ numbers.push(num);
41
+ }
42
+ }
43
+ if (invalid) {
44
+ console.log(`Please enter valid numbers between 1 and ${accounts.length}, separated by commas`);
45
+ continue;
46
+ }
47
+ if (numbers.length === 0) {
48
+ console.log(`Please enter at least one account number`);
49
+ continue;
50
+ }
51
+ const indices = numbers.map((n) => n - 1);
52
+ const selectedAccounts = indices
53
+ .map((i) => accounts[i])
54
+ .filter((acc) => acc !== undefined);
55
+ if (selectedAccounts.length === 0) {
56
+ console.log(`No valid accounts selected`);
57
+ continue;
58
+ }
59
+ console.log(`\nYou are about to delete ${selectedAccounts.length} account(s):`);
60
+ for (const acc of selectedAccounts) {
61
+ const label = acc.email || `Account ${acc.index + 1}`;
62
+ console.log(` - ${label}`);
63
+ }
64
+ const confirm = await rl.question(`\nConfirm deletion? (y/n): `);
65
+ const normalized = confirm.trim().toLowerCase();
66
+ if (normalized === 'y' || normalized === 'yes') {
67
+ return selectedAccounts.map((acc) => acc.index);
68
+ }
69
+ return null;
70
+ }
71
+ }
72
+ finally {
73
+ rl.close();
74
+ }
75
+ }
76
+ export async function promptLoginMode(existingAccounts) {
77
+ const rl = createInterface({ input, output });
78
+ try {
79
+ console.log(`\n${existingAccounts.length} account(s) saved:`);
80
+ for (const acc of existingAccounts) {
81
+ const label = acc.email || `Account ${acc.index + 1}`;
82
+ console.log(` ${acc.index + 1}. ${label}`);
83
+ }
84
+ console.log('');
85
+ while (true) {
86
+ const answer = await rl.question('(a)dd new account(s), (f)resh start, or (d)elete account? [a/f/d]: ');
87
+ const normalized = answer.trim().toLowerCase();
88
+ if (normalized === 'a' || normalized === 'add') {
89
+ return 'add';
90
+ }
91
+ if (normalized === 'f' || normalized === 'fresh') {
92
+ return 'fresh';
93
+ }
94
+ if (normalized === 'd' || normalized === 'delete') {
95
+ return 'delete';
96
+ }
97
+ console.log("Please enter 'a' to add accounts, 'f' to start fresh, or 'd' to delete account.");
98
+ }
99
+ }
100
+ finally {
101
+ rl.close();
102
+ }
103
+ }
@@ -0,0 +1,3 @@
1
+ export { configExists, getDefaultLogsDir, getProjectConfigPath, getUserConfigPath, loadConfig } from './loader';
2
+ export { DEFAULT_CONFIG, KiroConfigSchema } from './schema';
3
+ export type { KiroConfig } from './schema';
@@ -0,0 +1,2 @@
1
+ export { configExists, getDefaultLogsDir, getProjectConfigPath, getUserConfigPath, loadConfig } from './loader';
2
+ export { DEFAULT_CONFIG, KiroConfigSchema } from './schema';
@@ -0,0 +1,6 @@
1
+ import { type KiroConfig } from './schema';
2
+ export declare function getUserConfigPath(): string;
3
+ export declare function getProjectConfigPath(directory: string): string;
4
+ export declare function loadConfig(directory: string): KiroConfig;
5
+ export declare function configExists(path: string): boolean;
6
+ export declare function getDefaultLogsDir(): string;