@geminixiang/mikan 0.2.1 → 0.2.2

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 (60) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/adapters/slack/bot.d.ts +1 -0
  3. package/dist/adapters/slack/bot.d.ts.map +1 -1
  4. package/dist/adapters/slack/bot.js +43 -1
  5. package/dist/adapters/slack/bot.js.map +1 -1
  6. package/dist/admin/portal.d.ts +27 -0
  7. package/dist/admin/portal.d.ts.map +1 -0
  8. package/dist/admin/portal.js +2029 -0
  9. package/dist/admin/portal.js.map +1 -0
  10. package/dist/admin/store.d.ts +22 -0
  11. package/dist/admin/store.d.ts.map +1 -0
  12. package/dist/admin/store.js +39 -0
  13. package/dist/admin/store.js.map +1 -0
  14. package/dist/commands/admin.d.ts +8 -0
  15. package/dist/commands/admin.d.ts.map +1 -0
  16. package/dist/commands/admin.js +59 -0
  17. package/dist/commands/admin.js.map +1 -0
  18. package/dist/commands/auto-reply.d.ts.map +1 -1
  19. package/dist/commands/auto-reply.js +8 -7
  20. package/dist/commands/auto-reply.js.map +1 -1
  21. package/dist/commands/index.d.ts.map +1 -1
  22. package/dist/commands/index.js +2 -0
  23. package/dist/commands/index.js.map +1 -1
  24. package/dist/commands/login.d.ts.map +1 -1
  25. package/dist/commands/login.js +38 -14
  26. package/dist/commands/login.js.map +1 -1
  27. package/dist/commands/model.d.ts.map +1 -1
  28. package/dist/commands/model.js +2 -2
  29. package/dist/commands/model.js.map +1 -1
  30. package/dist/commands/new.d.ts.map +1 -1
  31. package/dist/commands/new.js +13 -3
  32. package/dist/commands/new.js.map +1 -1
  33. package/dist/commands/sandbox.d.ts.map +1 -1
  34. package/dist/commands/sandbox.js +2 -2
  35. package/dist/commands/sandbox.js.map +1 -1
  36. package/dist/commands/session-view.d.ts.map +1 -1
  37. package/dist/commands/session-view.js +3 -6
  38. package/dist/commands/session-view.js.map +1 -1
  39. package/dist/commands/types.d.ts +11 -0
  40. package/dist/commands/types.d.ts.map +1 -1
  41. package/dist/commands/types.js.map +1 -1
  42. package/dist/commands/utils.d.ts +1 -0
  43. package/dist/commands/utils.d.ts.map +1 -1
  44. package/dist/commands/utils.js +5 -0
  45. package/dist/commands/utils.js.map +1 -1
  46. package/dist/login/portal.d.ts +11 -1
  47. package/dist/login/portal.d.ts.map +1 -1
  48. package/dist/login/portal.js +57 -175
  49. package/dist/login/portal.js.map +1 -1
  50. package/dist/main.d.ts.map +1 -1
  51. package/dist/main.js +5 -1
  52. package/dist/main.js.map +1 -1
  53. package/dist/portal-shell.d.ts +30 -0
  54. package/dist/portal-shell.d.ts.map +1 -0
  55. package/dist/portal-shell.js +371 -0
  56. package/dist/portal-shell.js.map +1 -0
  57. package/dist/session-view/portal.d.ts.map +1 -1
  58. package/dist/session-view/portal.js +88 -242
  59. package/dist/session-view/portal.js.map +1 -1
  60. package/package.json +1 -1
@@ -1,5 +1,7 @@
1
1
  import { createHash, randomBytes } from "crypto";
2
2
  import { createServer } from "http";
3
+ import { handleAdminRequest } from "../admin/portal.js";
4
+ import { renderPortalShell } from "../portal-shell.js";
3
5
  import { resolveLinkBaseUrl } from "../config.js";
4
6
  import { handleSessionViewRequest, } from "../session-view/portal.js";
5
7
  import { getOAuthServices, resolveOAuthService, } from "./index.js";
@@ -185,7 +187,7 @@ const SECRET_PRESETS = [
185
187
  * POST /api/oauth/start — creates provider OAuth redirect URL
186
188
  * GET /oauth/callback — OAuth callback endpoint
187
189
  */
188
- export function startLinkServer(port, linkTokenStore, vaultManager, notify, sessionViewTokenStore, sessionViewInteractive) {
190
+ export function startLinkServer(port, linkTokenStore, vaultManager, notify, sessionViewTokenStore, sessionViewInteractive, adminOptions) {
189
191
  const oauthStates = new Map();
190
192
  const server = createServer(async (req, res) => {
191
193
  try {
@@ -195,6 +197,20 @@ export function startLinkServer(port, linkTokenStore, vaultManager, notify, sess
195
197
  res.end(JSON.stringify({ ok: true }));
196
198
  return;
197
199
  }
200
+ if (adminOptions?.adminTokenStore &&
201
+ handleAdminRequest(req, res, url, {
202
+ vaultManager,
203
+ linkTokenStore,
204
+ sessionViewTokenStore,
205
+ adminTokenStore: adminOptions.adminTokenStore,
206
+ portalBaseUrl: resolveLinkBaseUrl() ?? undefined,
207
+ workingDir: adminOptions.workingDir,
208
+ runtime: adminOptions.runtime,
209
+ sandbox: adminOptions.sandbox,
210
+ botsByPlatform: adminOptions.botsByPlatform,
211
+ })) {
212
+ return;
213
+ }
198
214
  if (await handleSessionViewRequest(req, res, url, sessionViewTokenStore, sessionViewInteractive)) {
199
215
  return;
200
216
  }
@@ -385,145 +401,53 @@ async function readJsonBody(req, res, onBody) {
385
401
  function esc(s) {
386
402
  return s.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
387
403
  }
388
- const sharedPageStyles = `
389
- :root {
390
- color-scheme: light;
391
- --bg: #f5f1e8;
392
- --panel: rgba(255, 255, 255, 0.9);
393
- --panel-border: rgba(28, 30, 33, 0.08);
394
- --text: #1c1e21;
395
- --muted: #5d5f64;
396
- --button: #1c1e21;
397
- --button-hover: #2c3035;
398
- --button-disabled: #8f949b;
399
- --field-border: #c9cfd6;
400
- --field-focus: #1c1e21;
401
- --ok-bg: #dff4e4;
402
- --ok-text: #1f5b34;
403
- --err-bg: #fde2e2;
404
- --err-text: #8a2f2f;
405
- }
406
-
407
- * { box-sizing: border-box; }
408
-
409
- body {
410
- margin: 0;
411
- min-height: 100vh;
412
- padding: 32px 20px;
413
- display: grid;
414
- grid-template-columns: minmax(0, 560px);
415
- justify-content: center;
416
- align-content: start;
417
- background:
418
- radial-gradient(circle at top, rgba(255, 255, 255, 0.7), transparent 45%),
419
- linear-gradient(180deg, #faf7f0 0%, var(--bg) 100%);
420
- color: var(--text);
421
- font-family:
422
- "SF Pro Text",
423
- "Segoe UI",
424
- system-ui,
425
- sans-serif;
426
- }
404
+ const loginViewStyles = `
405
+ /* Login portal inherits all base chrome from the shared shell.
406
+ This module only adds preset cards, service logos, help popovers,
407
+ and the mode toggle. */
427
408
 
428
- .shell {
429
- width: 100%;
430
- min-width: 0;
431
- display: grid;
432
- gap: 16px;
433
- align-content: start;
434
- }
409
+ p { margin: 0; color: var(--muted); font-size: 0.92rem; line-height: 1.55; }
435
410
 
436
- .card {
437
- padding: 28px;
438
- border: 1px solid var(--panel-border);
439
- border-radius: 20px;
440
- background: var(--panel);
441
- box-shadow: 0 18px 48px rgba(28, 30, 33, 0.08);
442
- backdrop-filter: blur(8px);
443
- }
444
-
445
- .eyebrow {
446
- margin: 0 0 10px;
447
- color: var(--muted);
448
- font-size: 0.82rem;
449
- font-weight: 700;
450
- letter-spacing: 0.08em;
451
- text-transform: uppercase;
452
- }
453
-
454
- h1 {
455
- margin: 0 0 10px;
456
- font-size: clamp(1.5rem, 2vw, 1.8rem);
457
- line-height: 1.15;
458
- text-wrap: balance;
459
- }
460
-
461
- p {
462
- margin: 0;
463
- color: var(--muted);
464
- font-size: 0.98rem;
465
- line-height: 1.5;
466
- }
467
-
468
- .stack > * + * {
469
- margin-top: 14px;
470
- }
411
+ .stack > * + * { margin-top: 14px; }
471
412
 
472
413
  label {
473
414
  display: block;
474
415
  margin-bottom: 6px;
475
- font-size: 0.92rem;
476
- font-weight: 650;
477
- }
478
-
479
- input,
480
- select,
481
- button {
482
- font: inherit;
416
+ font-size: 0.86rem;
417
+ font-weight: 600;
418
+ color: var(--text);
483
419
  }
484
420
 
485
- input,
486
- select {
421
+ input, select {
487
422
  width: 100%;
488
- padding: 12px 14px;
489
- border: 1px solid var(--field-border);
490
- border-radius: 12px;
423
+ padding: 10px 12px;
424
+ border: 1px solid var(--border);
425
+ border-radius: 10px;
491
426
  background: #fff;
492
427
  color: var(--text);
428
+ font: inherit;
493
429
  }
494
430
 
495
431
  input:focus-visible,
496
- select:focus-visible,
497
- button:focus-visible {
498
- outline: 2px solid var(--field-focus);
499
- outline-offset: 2px;
500
- }
501
-
502
- code {
503
- font-family: "SFMono-Regular", ui-monospace, SFMono-Regular, Menlo, monospace;
504
- font-size: 0.92em;
505
- overflow-wrap: anywhere;
432
+ select:focus-visible {
433
+ outline: 2px solid var(--text);
434
+ outline-offset: 1px;
506
435
  }
507
436
 
508
437
  .primary-button {
509
438
  width: 100%;
510
- padding: 13px 18px;
439
+ padding: 12px 18px;
511
440
  border: none;
512
441
  border-radius: 12px;
513
- background: var(--button);
442
+ background: var(--text);
514
443
  color: #fff;
515
444
  cursor: pointer;
516
- transition: background-color 160ms ease;
445
+ font: 500 0.95rem/1.2 'DM Sans', sans-serif;
446
+ transition: opacity 120ms;
517
447
  }
518
448
 
519
- .primary-button:hover {
520
- background: var(--button-hover);
521
- }
522
-
523
- .primary-button:disabled {
524
- background: var(--button-disabled);
525
- cursor: default;
526
- }
449
+ .primary-button:hover:not(:disabled) { opacity: 0.85; }
450
+ .primary-button:disabled { opacity: 0.5; cursor: default; }
527
451
 
528
452
  .service-logo {
529
453
  display: inline-flex;
@@ -620,7 +544,7 @@ const sharedPageStyles = `
620
544
  width: 18px;
621
545
  height: 18px;
622
546
  padding: 0;
623
- border: 1px solid var(--field-border);
547
+ border: 1px solid var(--border);
624
548
  border-radius: 50%;
625
549
  background: rgba(255, 255, 255, 0.9);
626
550
  color: var(--muted);
@@ -644,7 +568,7 @@ const sharedPageStyles = `
644
568
  width: max-content;
645
569
  max-width: 280px;
646
570
  padding: 10px 12px;
647
- border: 1px solid var(--panel-border);
571
+ border: 1px solid var(--border);
648
572
  border-radius: 10px;
649
573
  background: #fff;
650
574
  color: var(--text);
@@ -677,7 +601,7 @@ const sharedPageStyles = `
677
601
  gap: 8px;
678
602
  margin: 0;
679
603
  padding: 10px 12px;
680
- border: 1px solid var(--field-border);
604
+ border: 1px solid var(--border);
681
605
  border-radius: 999px;
682
606
  background: rgba(255, 255, 255, 0.85);
683
607
  font-weight: 500;
@@ -733,7 +657,7 @@ const sharedPageStyles = `
733
657
  .secrets-summary {
734
658
  margin-top: 18px;
735
659
  padding: 14px 16px;
736
- border: 1px solid var(--panel-border);
660
+ border: 1px solid var(--border);
737
661
  border-radius: 14px;
738
662
  background: rgba(255, 255, 255, 0.72);
739
663
  }
@@ -763,62 +687,20 @@ const sharedPageStyles = `
763
687
  }
764
688
 
765
689
  @media (max-width: 640px) {
766
- body {
767
- padding: 16px 12px;
768
- }
769
-
770
- .shell {
771
- gap: 12px;
772
- }
773
-
774
- .card {
775
- padding: 20px;
776
- border-radius: 16px;
777
- }
778
-
779
- /* Mode toggle pills fill the row evenly */
780
- .mode label {
781
- flex: 1;
782
- justify-content: center;
783
- }
784
-
785
- /* Larger touch targets */
786
- input,
787
- select {
788
- padding: 14px;
789
- }
790
-
791
- .primary-button {
792
- padding: 15px 18px;
793
- }
794
-
795
- /* Prevent help popover from overflowing the viewport */
796
- .help-content {
797
- max-width: min(260px, calc(100vw - 40px));
798
- }
799
-
800
- /* Right-align popovers that sit near the right edge */
801
- .provider-header .help-content {
802
- left: auto;
803
- right: 0;
804
- }
690
+ .mode label { flex: 1; justify-content: center; }
691
+ input, select { padding: 12px; }
692
+ .primary-button { padding: 14px 18px; }
693
+ .help-content { max-width: min(260px, calc(100vw - 40px)); }
694
+ .provider-header .help-content { left: auto; right: 0; }
805
695
  }
806
696
  `;
807
697
  function renderHtmlDocument(title, shellContent) {
808
- return `<!DOCTYPE html>
809
- <html lang="en">
810
- <head>
811
- <meta charset="utf-8">
812
- <meta name="viewport" content="width=device-width, initial-scale=1">
813
- <title>${esc(title)} — ${PRODUCT_NAME}</title>
814
- <style>${sharedPageStyles}</style>
815
- </head>
816
- <body>
817
- <main class="shell">
818
- ${shellContent}
819
- </main>
820
- </body>
821
- </html>`;
698
+ return renderPortalShell({
699
+ activeView: "vault",
700
+ pageTitle: "Vault",
701
+ body: shellContent,
702
+ extraStyles: loginViewStyles,
703
+ });
822
704
  }
823
705
  function renderPageDocument(title, body) {
824
706
  return renderHtmlDocument(title, `<section class="card">${body}</section>`);
@@ -827,7 +709,7 @@ function renderStatusPage(title, message, tone, options) {
827
709
  const closeNote = options?.closeNote ? '<p class="close-note">You can close this tab.</p>' : "";
828
710
  return renderPageDocument(title, `<div class="stack">
829
711
  <p class="eyebrow">${PRODUCT_NAME}</p>
830
- <h1>${esc(title)}</h1>
712
+ <h1 class="page-title">${esc(title)}</h1>
831
713
  <div class="status ${tone}">${esc(message)}</div>
832
714
  ${closeNote}
833
715
  </div>`);
@@ -961,7 +843,7 @@ function renderCredentialPage(token, title, defaultMode, initialEnvKey, secretLa
961
843
  const presetCards = SECRET_PRESETS.map(renderPresetProviderCard).join("\n");
962
844
  return renderHtmlDocument("Login", `<section class="card stack">
963
845
  <p class="eyebrow">${PRODUCT_NAME}</p>
964
- <h1>${esc(title)}</h1>
846
+ <h1 class="page-title">${esc(title)}</h1>
965
847
  <p>Your personal sandbox is already provisioned automatically.</p>
966
848
  <p>${esc(helpText)}</p>
967
849
  ${renderSecretsSummary(existingSecrets)}