@portel/photon 1.20.0 → 1.20.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 (86) hide show
  1. package/dist/auto-ui/beam/routes/api-config.d.ts.map +1 -1
  2. package/dist/auto-ui/beam/routes/api-config.js +161 -20
  3. package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
  4. package/dist/auto-ui/beam.d.ts.map +1 -1
  5. package/dist/auto-ui/beam.js +4 -3
  6. package/dist/auto-ui/beam.js.map +1 -1
  7. package/dist/auto-ui/bridge/renderers.d.ts.map +1 -1
  8. package/dist/auto-ui/bridge/renderers.js +12 -4
  9. package/dist/auto-ui/bridge/renderers.js.map +1 -1
  10. package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
  11. package/dist/auto-ui/streamable-http-transport.js +115 -28
  12. package/dist/auto-ui/streamable-http-transport.js.map +1 -1
  13. package/dist/beam-form.bundle.js +19 -182
  14. package/dist/beam-form.bundle.js.map +4 -4
  15. package/dist/beam.bundle.js +743 -311
  16. package/dist/beam.bundle.js.map +4 -4
  17. package/dist/cli/commands/beam.d.ts.map +1 -1
  18. package/dist/cli/commands/beam.js +47 -30
  19. package/dist/cli/commands/beam.js.map +1 -1
  20. package/dist/cli/commands/build.d.ts.map +1 -1
  21. package/dist/cli/commands/build.js +27 -2
  22. package/dist/cli/commands/build.js.map +1 -1
  23. package/dist/cli/commands/daemon.d.ts.map +1 -1
  24. package/dist/cli/commands/daemon.js +12 -6
  25. package/dist/cli/commands/daemon.js.map +1 -1
  26. package/dist/cli/commands/mcp.d.ts.map +1 -1
  27. package/dist/cli/commands/mcp.js +18 -6
  28. package/dist/cli/commands/mcp.js.map +1 -1
  29. package/dist/cli/commands/serve.d.ts.map +1 -1
  30. package/dist/cli/commands/serve.js +14 -2
  31. package/dist/cli/commands/serve.js.map +1 -1
  32. package/dist/cli-alias.d.ts.map +1 -1
  33. package/dist/cli-alias.js +2 -3
  34. package/dist/cli-alias.js.map +1 -1
  35. package/dist/context-store.d.ts +4 -4
  36. package/dist/context-store.d.ts.map +1 -1
  37. package/dist/context-store.js +18 -15
  38. package/dist/context-store.js.map +1 -1
  39. package/dist/context.d.ts +25 -2
  40. package/dist/context.d.ts.map +1 -1
  41. package/dist/context.js +69 -4
  42. package/dist/context.js.map +1 -1
  43. package/dist/daemon/client.d.ts.map +1 -1
  44. package/dist/daemon/client.js +4 -1
  45. package/dist/daemon/client.js.map +1 -1
  46. package/dist/daemon/manager.d.ts +2 -0
  47. package/dist/daemon/manager.d.ts.map +1 -1
  48. package/dist/daemon/manager.js +40 -8
  49. package/dist/daemon/manager.js.map +1 -1
  50. package/dist/daemon/server.js +59 -15
  51. package/dist/daemon/server.js.map +1 -1
  52. package/dist/daemon/worker-host.js +7 -0
  53. package/dist/daemon/worker-host.js.map +1 -1
  54. package/dist/daemon/worker-manager.d.ts.map +1 -1
  55. package/dist/daemon/worker-manager.js +58 -10
  56. package/dist/daemon/worker-manager.js.map +1 -1
  57. package/dist/daemon/worker-protocol.d.ts +3 -0
  58. package/dist/daemon/worker-protocol.d.ts.map +1 -1
  59. package/dist/deploy/cloudflare.d.ts.map +1 -1
  60. package/dist/deploy/cloudflare.js +2 -4
  61. package/dist/deploy/cloudflare.js.map +1 -1
  62. package/dist/loader.d.ts +7 -0
  63. package/dist/loader.d.ts.map +1 -1
  64. package/dist/loader.js +56 -2
  65. package/dist/loader.js.map +1 -1
  66. package/dist/marketplace-manager.d.ts +1 -1
  67. package/dist/marketplace-manager.d.ts.map +1 -1
  68. package/dist/marketplace-manager.js +5 -4
  69. package/dist/marketplace-manager.js.map +1 -1
  70. package/dist/photon-cli-runner.d.ts.map +1 -1
  71. package/dist/photon-cli-runner.js +40 -21
  72. package/dist/photon-cli-runner.js.map +1 -1
  73. package/dist/photon-doc-extractor.d.ts.map +1 -1
  74. package/dist/photon-doc-extractor.js +59 -15
  75. package/dist/photon-doc-extractor.js.map +1 -1
  76. package/dist/server.d.ts.map +1 -1
  77. package/dist/server.js +14 -16
  78. package/dist/server.js.map +1 -1
  79. package/dist/shared-utils.d.ts +4 -0
  80. package/dist/shared-utils.d.ts.map +1 -1
  81. package/dist/shared-utils.js +22 -0
  82. package/dist/shared-utils.js.map +1 -1
  83. package/dist/template-manager.d.ts.map +1 -1
  84. package/dist/template-manager.js +56 -234
  85. package/dist/template-manager.js.map +1 -1
  86. package/package.json +2 -2
@@ -19269,187 +19269,33 @@ function showToast(message, type = "info", duration4 = 3e3, action) {
19269
19269
  ToastManager.show(message, type, duration4, action);
19270
19270
  }
19271
19271
 
19272
- // src/auto-ui/frontend/components/confirm-dialog.ts
19273
- var ConfirmDialog = class extends i4 {
19274
- constructor() {
19275
- super(...arguments);
19276
- this.open = false;
19277
- this.message = "";
19278
- this.confirmLabel = "OK";
19279
- this.cancelLabel = "Cancel";
19280
- this.destructive = false;
19281
- }
19282
- show(message, options) {
19283
- this.message = message;
19284
- this.confirmLabel = options?.confirm ?? "OK";
19285
- this.cancelLabel = options?.cancel ?? "Cancel";
19286
- this.destructive = options?.destructive ?? false;
19287
- this.open = true;
19288
- return new Promise((resolve2) => {
19289
- this._resolve = resolve2;
19290
- });
19291
- }
19292
- _handleConfirm() {
19293
- this.open = false;
19294
- this._resolve?.(true);
19295
- }
19296
- _handleCancel() {
19297
- this.open = false;
19298
- this._resolve?.(false);
19299
- }
19300
- _handleKeydown(e8) {
19301
- if (e8.key === "Escape") this._handleCancel();
19302
- if (e8.key === "Enter") this._handleConfirm();
19303
- }
19304
- render() {
19305
- return b2`
19306
- <div class="dialog" @keydown=${(e8) => this._handleKeydown(e8)}>
19307
- <div class="message">${this.message}</div>
19308
- <div class="actions">
19309
- <button class="btn-cancel" @click=${() => this._handleCancel()}>
19310
- ${this.cancelLabel}
19311
- </button>
19312
- <button
19313
- class="btn-confirm ${this.destructive ? "destructive" : ""}"
19314
- @click=${() => this._handleConfirm()}
19315
- >
19316
- ${this.confirmLabel}
19317
- </button>
19318
- </div>
19319
- </div>
19320
- `;
19321
- }
19322
- };
19323
- ConfirmDialog.styles = [
19324
- theme,
19325
- i`
19326
- :host {
19327
- display: none;
19328
- }
19329
-
19330
- @keyframes backdrop-in {
19331
- from {
19332
- opacity: 0;
19333
- }
19334
- to {
19335
- opacity: 1;
19336
- }
19337
- }
19338
-
19339
- @keyframes content-in {
19340
- from {
19341
- opacity: 0;
19342
- transform: scale(0.95) translateY(8px);
19343
- }
19344
- to {
19345
- opacity: 1;
19346
- transform: scale(1) translateY(0);
19347
- }
19348
- }
19349
-
19350
- :host([open]) {
19351
- display: flex;
19352
- position: fixed;
19353
- inset: 0;
19354
- background: rgba(0, 0, 0, 0.6);
19355
- backdrop-filter: blur(4px);
19356
- z-index: 10001;
19357
- align-items: center;
19358
- justify-content: center;
19359
- animation: backdrop-in 0.15s ease-out both;
19360
- }
19361
-
19362
- .dialog {
19363
- background: var(--bg-panel);
19364
- border: 1px solid var(--border-glass);
19365
- border-radius: var(--radius-md, 12px);
19366
- padding: 24px;
19367
- max-width: 400px;
19368
- width: 90%;
19369
- box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4);
19370
- animation: content-in 0.2s cubic-bezier(0.16, 1, 0.3, 1) both;
19371
- animation-delay: 0.05s;
19372
- }
19373
-
19374
- .message {
19375
- font-size: 14px;
19376
- line-height: 1.5;
19377
- color: var(--t-primary);
19378
- margin-bottom: 20px;
19379
- }
19380
-
19381
- .actions {
19382
- display: flex;
19383
- justify-content: flex-end;
19384
- gap: 8px;
19385
- }
19386
-
19387
- button {
19388
- padding: 8px 16px;
19389
- border-radius: var(--radius-sm, 6px);
19390
- font-size: 13px;
19391
- font-weight: 500;
19392
- cursor: pointer;
19393
- transition: all 0.15s ease;
19394
- font-family: inherit;
19395
- border: none;
19396
- }
19397
-
19398
- .btn-cancel {
19399
- background: var(--bg-glass);
19400
- color: var(--t-primary);
19401
- border: 1px solid var(--border-glass);
19402
- }
19403
-
19404
- .btn-cancel:hover {
19405
- background: var(--bg-glass-strong);
19406
- }
19407
-
19408
- .btn-confirm {
19409
- background: var(--accent);
19410
- color: #fff;
19411
- }
19412
-
19413
- .btn-confirm:hover {
19414
- opacity: 0.9;
19415
- }
19416
-
19417
- .btn-confirm.destructive {
19418
- background: hsl(0, 60%, 50%);
19419
- }
19420
-
19421
- .btn-confirm.destructive:hover {
19422
- background: hsl(0, 60%, 45%);
19423
- }
19424
- `
19425
- ];
19426
- __decorateClass([
19427
- n4({ type: Boolean, reflect: true })
19428
- ], ConfirmDialog.prototype, "open", 2);
19429
- __decorateClass([
19430
- n4({ type: String })
19431
- ], ConfirmDialog.prototype, "message", 2);
19432
- __decorateClass([
19433
- n4({ type: String })
19434
- ], ConfirmDialog.prototype, "confirmLabel", 2);
19435
- __decorateClass([
19436
- n4({ type: String })
19437
- ], ConfirmDialog.prototype, "cancelLabel", 2);
19438
- __decorateClass([
19439
- n4({ type: Boolean })
19440
- ], ConfirmDialog.prototype, "destructive", 2);
19441
- ConfirmDialog = __decorateClass([
19442
- t4("confirm-dialog")
19443
- ], ConfirmDialog);
19444
- async function confirmDialog(message, options) {
19445
- const beamApp = document.querySelector("beam-app");
19446
- const root = beamApp?.shadowRoot ?? document.body;
19447
- let dialog = root.querySelector("confirm-dialog");
19448
- if (!dialog) {
19449
- dialog = document.createElement("confirm-dialog");
19450
- root.appendChild(dialog);
19451
- }
19452
- return dialog.show(message, options);
19272
+ // src/auto-ui/frontend/utils/elicit.ts
19273
+ function elicit(data) {
19274
+ return new Promise((resolve2) => {
19275
+ document.dispatchEvent(
19276
+ new CustomEvent("beam:elicit-local", {
19277
+ detail: { data, resolve: resolve2 }
19278
+ })
19279
+ );
19280
+ });
19281
+ }
19282
+ async function confirmElicit(message, options) {
19283
+ const result = await elicit({
19284
+ ask: "confirm",
19285
+ message,
19286
+ default: false,
19287
+ ...options?.confirm && { placeholder: options.confirm }
19288
+ });
19289
+ return result.action === "accept" && result.value !== false;
19290
+ }
19291
+ async function promptElicit(message, defaultValue = "") {
19292
+ const result = await elicit({
19293
+ ask: "text",
19294
+ message,
19295
+ default: defaultValue
19296
+ });
19297
+ if (result.action === "cancel") return null;
19298
+ return result.value ?? null;
19453
19299
  }
19454
19300
 
19455
19301
  // node_modules/lit-html/directives/unsafe-svg.js
@@ -20857,6 +20703,258 @@ function loadSavedThemeConfig() {
20857
20703
  return null;
20858
20704
  }
20859
20705
 
20706
+ // src/auto-ui/frontend/components/pending-approvals.ts
20707
+ var PendingApprovals = class extends i4 {
20708
+ constructor() {
20709
+ super(...arguments);
20710
+ this.approvals = [];
20711
+ this._resolving = /* @__PURE__ */ new Set();
20712
+ }
20713
+ render() {
20714
+ return b2`
20715
+ <div class="header">
20716
+ <span class="header-title">${shieldCheck} Pending Approvals</span>
20717
+ <button
20718
+ class="close-btn"
20719
+ @click=${() => this.dispatchEvent(new CustomEvent("close", { bubbles: true, composed: true }))}
20720
+ aria-label="Close"
20721
+ >
20722
+ ${xMark}
20723
+ </button>
20724
+ </div>
20725
+
20726
+ <div class="content">
20727
+ ${this.approvals.length === 0 ? b2`
20728
+ <div class="empty">
20729
+ ${shieldCheck}
20730
+ <div>No pending approvals</div>
20731
+ </div>
20732
+ ` : this.approvals.map((a5) => this._renderApproval(a5))}
20733
+ </div>
20734
+ `;
20735
+ }
20736
+ _renderApproval(approval) {
20737
+ const isResolving = this._resolving.has(approval.id);
20738
+ const timeLeft = this._formatTimeLeft(approval.expiresAt);
20739
+ return b2`
20740
+ <div class="approval-card ${approval.destructive ? "destructive" : ""}">
20741
+ <div class="approval-meta">
20742
+ <span>${approval.photon}.${approval.method}</span>
20743
+ ${approval.destructive ? b2`<span class="destructive-label">${warning} destructive</span>` : A}
20744
+ </div>
20745
+ <div class="approval-message">${approval.message}</div>
20746
+ ${approval.preview ? b2`<div class="preview">
20747
+ ${typeof approval.preview === "string" ? approval.preview : JSON.stringify(approval.preview, null, 2)}
20748
+ </div>` : A}
20749
+ <div class="expiry">Expires ${timeLeft}</div>
20750
+ <div class="actions">
20751
+ <button
20752
+ class="btn btn-reject"
20753
+ ?disabled=${isResolving}
20754
+ @click=${() => this._respond(approval, false)}
20755
+ >
20756
+ ${xMark} Reject
20757
+ </button>
20758
+ <button
20759
+ class="btn btn-approve"
20760
+ ?disabled=${isResolving}
20761
+ @click=${() => this._respond(approval, true)}
20762
+ >
20763
+ ${check} Approve
20764
+ </button>
20765
+ </div>
20766
+ </div>
20767
+ `;
20768
+ }
20769
+ _respond(approval, approved) {
20770
+ this._resolving.add(approval.id);
20771
+ this.requestUpdate();
20772
+ this.dispatchEvent(
20773
+ new CustomEvent("approval-response", {
20774
+ detail: { approvalId: approval.id, photon: approval.photon, approved },
20775
+ bubbles: true,
20776
+ composed: true
20777
+ })
20778
+ );
20779
+ }
20780
+ _formatTimeLeft(expiresAt) {
20781
+ const diff = new Date(expiresAt).getTime() - Date.now();
20782
+ if (diff <= 0) return "expired";
20783
+ const hours = Math.floor(diff / (1e3 * 60 * 60));
20784
+ const minutes = Math.floor(diff % (1e3 * 60 * 60) / (1e3 * 60));
20785
+ if (hours > 0) return `in ${hours}h ${minutes}m`;
20786
+ return `in ${minutes}m`;
20787
+ }
20788
+ };
20789
+ PendingApprovals.styles = [
20790
+ theme,
20791
+ buttons,
20792
+ i`
20793
+ :host {
20794
+ display: flex;
20795
+ flex-direction: column;
20796
+ height: 100%;
20797
+ color: var(--t-primary);
20798
+ }
20799
+
20800
+ .header {
20801
+ display: flex;
20802
+ align-items: center;
20803
+ justify-content: space-between;
20804
+ padding: var(--space-sm) var(--space-md);
20805
+ border-bottom: 1px solid var(--t-border);
20806
+ }
20807
+
20808
+ .header-title {
20809
+ display: flex;
20810
+ align-items: center;
20811
+ gap: var(--space-xs);
20812
+ font-weight: 600;
20813
+ font-size: var(--text-sm);
20814
+ }
20815
+
20816
+ .close-btn {
20817
+ background: none;
20818
+ border: none;
20819
+ color: var(--t-secondary);
20820
+ cursor: pointer;
20821
+ padding: var(--space-xs);
20822
+ border-radius: var(--radius-sm);
20823
+ display: flex;
20824
+ align-items: center;
20825
+ }
20826
+
20827
+ .close-btn:hover {
20828
+ background: var(--t-hover);
20829
+ }
20830
+
20831
+ .content {
20832
+ flex: 1;
20833
+ overflow-y: auto;
20834
+ padding: var(--space-sm);
20835
+ }
20836
+
20837
+ .empty {
20838
+ display: flex;
20839
+ flex-direction: column;
20840
+ align-items: center;
20841
+ justify-content: center;
20842
+ padding: var(--space-xl);
20843
+ text-align: center;
20844
+ color: var(--t-secondary);
20845
+ }
20846
+
20847
+ .empty svg {
20848
+ opacity: 0.4;
20849
+ margin-bottom: var(--space-sm);
20850
+ width: 32px;
20851
+ height: 32px;
20852
+ }
20853
+
20854
+ .approval-card {
20855
+ border: 1px solid var(--t-border);
20856
+ border-radius: var(--radius-md);
20857
+ padding: var(--space-sm) var(--space-md);
20858
+ margin-bottom: var(--space-sm);
20859
+ background: var(--t-surface);
20860
+ }
20861
+
20862
+ .approval-card.destructive {
20863
+ border-color: hsl(0, 60%, 50%);
20864
+ }
20865
+
20866
+ .approval-meta {
20867
+ display: flex;
20868
+ align-items: center;
20869
+ gap: var(--space-xs);
20870
+ font-size: var(--text-xs);
20871
+ color: var(--t-secondary);
20872
+ margin-bottom: var(--space-xs);
20873
+ }
20874
+
20875
+ .approval-message {
20876
+ font-size: var(--text-sm);
20877
+ margin-bottom: var(--space-sm);
20878
+ }
20879
+
20880
+ .preview {
20881
+ font-size: var(--text-xs);
20882
+ color: var(--t-secondary);
20883
+ background: var(--t-bg);
20884
+ padding: var(--space-xs) var(--space-sm);
20885
+ border-radius: var(--radius-sm);
20886
+ margin-bottom: var(--space-sm);
20887
+ max-height: 80px;
20888
+ overflow-y: auto;
20889
+ font-family: var(--font-mono);
20890
+ white-space: pre-wrap;
20891
+ }
20892
+
20893
+ .expiry {
20894
+ font-size: var(--text-xs);
20895
+ color: var(--t-secondary);
20896
+ }
20897
+
20898
+ .actions {
20899
+ display: flex;
20900
+ gap: var(--space-xs);
20901
+ margin-top: var(--space-sm);
20902
+ }
20903
+
20904
+ .btn {
20905
+ flex: 1;
20906
+ padding: var(--space-xs) var(--space-sm);
20907
+ border: 1px solid var(--t-border);
20908
+ border-radius: var(--radius-sm);
20909
+ cursor: pointer;
20910
+ font-size: var(--text-xs);
20911
+ font-weight: 600;
20912
+ display: flex;
20913
+ align-items: center;
20914
+ justify-content: center;
20915
+ gap: var(--space-xs);
20916
+ transition: all 0.15s;
20917
+ }
20918
+
20919
+ .btn-approve {
20920
+ background: hsl(142, 60%, 45%);
20921
+ color: white;
20922
+ border-color: hsl(142, 60%, 40%);
20923
+ }
20924
+
20925
+ .btn-approve:hover {
20926
+ background: hsl(142, 60%, 40%);
20927
+ }
20928
+
20929
+ .btn-reject {
20930
+ background: var(--t-surface);
20931
+ color: var(--t-primary);
20932
+ }
20933
+
20934
+ .btn-reject:hover {
20935
+ background: var(--t-hover);
20936
+ }
20937
+
20938
+ .destructive-label {
20939
+ display: inline-flex;
20940
+ align-items: center;
20941
+ gap: 2px;
20942
+ color: hsl(0, 70%, 55%);
20943
+ font-size: var(--text-2xs);
20944
+ font-weight: 600;
20945
+ }
20946
+ `
20947
+ ];
20948
+ __decorateClass([
20949
+ n4({ type: Array })
20950
+ ], PendingApprovals.prototype, "approvals", 2);
20951
+ __decorateClass([
20952
+ r5()
20953
+ ], PendingApprovals.prototype, "_resolving", 2);
20954
+ PendingApprovals = __decorateClass([
20955
+ t4("pending-approvals")
20956
+ ], PendingApprovals);
20957
+
20860
20958
  // src/auto-ui/frontend/services/photon-instance-manager.ts
20861
20959
  var SimpleEventEmitter = class {
20862
20960
  constructor() {
@@ -21645,6 +21743,32 @@ var MCPClientService = class {
21645
21743
  return { success: false };
21646
21744
  }
21647
21745
  }
21746
+ /**
21747
+ * Send approval response (approve/reject) for a pending approval
21748
+ */
21749
+ async sendApprovalResponse(approvalId, photon, approved) {
21750
+ try {
21751
+ await this.sendRequest("beam/approval-response", {
21752
+ approvalId,
21753
+ photon,
21754
+ approved
21755
+ });
21756
+ return { success: true };
21757
+ } catch {
21758
+ return { success: false };
21759
+ }
21760
+ }
21761
+ /**
21762
+ * Fetch all pending approvals from the server
21763
+ */
21764
+ async fetchPendingApprovals() {
21765
+ try {
21766
+ const result = await this.sendRequest("beam/approvals-list", {});
21767
+ return result?.approvals || [];
21768
+ } catch {
21769
+ return [];
21770
+ }
21771
+ }
21648
21772
  /**
21649
21773
  * Get rich help documentation for a photon via beam/photon-help tool
21650
21774
  */
@@ -21938,6 +22062,12 @@ var MCPClientService = class {
21938
22062
  case "beam/elicitation":
21939
22063
  this.emit("elicitation", notification.params);
21940
22064
  break;
22065
+ case "beam/elicitation-deferred":
22066
+ this.emit("elicitation-deferred", notification.params);
22067
+ break;
22068
+ case "beam/approval-resolved":
22069
+ this.emit("approval-resolved", notification.params);
22070
+ break;
21941
22071
  case "beam/result":
21942
22072
  this.emit("result", notification.params);
21943
22073
  break;
@@ -22542,6 +22672,8 @@ var BeamApp = class extends i4 {
22542
22672
  this._photonHelpLoading = false;
22543
22673
  this._elicitationData = null;
22544
22674
  this._showElicitation = false;
22675
+ this._showApprovals = false;
22676
+ this._pendingApprovalsList = [];
22545
22677
  this._protocolMode = "legacy";
22546
22678
  this._selectedMcpAppUri = null;
22547
22679
  this._mcpReady = false;
@@ -22889,7 +23021,7 @@ var BeamApp = class extends i4 {
22889
23021
  this._handleRemove = async () => {
22890
23022
  this._closeSettingsMenu();
22891
23023
  if (this._selectedPhoton && this._mcpReady) {
22892
- if (await confirmDialog(`Remove ${this._selectedPhoton.name} from this workspace?`, {
23024
+ if (await confirmElicit(`Remove ${this._selectedPhoton.name} from this workspace?`, {
22893
23025
  confirm: "Remove",
22894
23026
  destructive: true
22895
23027
  })) {
@@ -22900,22 +23032,42 @@ var BeamApp = class extends i4 {
22900
23032
  }
22901
23033
  }
22902
23034
  };
22903
- this._handleCopyMCPConfig = async () => {
23035
+ this._copyConfigSnippet = async (transport) => {
22904
23036
  if (!this._selectedPhoton) return;
23037
+ const name2 = this._selectedPhoton.name;
22905
23038
  try {
22906
- const res = await fetch(
22907
- `/api/export/mcp-config?photon=${encodeURIComponent(this._selectedPhoton.name)}`,
22908
- {
22909
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
23039
+ let config3;
23040
+ if (transport === "url") {
23041
+ const beamUrl = `${location.protocol}//${location.host}/mcp`;
23042
+ config3 = { mcpServers: { [name2]: { url: beamUrl } } };
23043
+ } else {
23044
+ const res = await fetch("/api/export/mcp-config", {
23045
+ signal: AbortSignal.timeout(3e3)
23046
+ });
23047
+ if (res.ok) {
23048
+ const all = await res.json();
23049
+ const entry = all.mcpServers?.[name2];
23050
+ if (entry) {
23051
+ config3 = { mcpServers: { [name2]: entry } };
23052
+ } else {
23053
+ config3 = {
23054
+ mcpServers: {
23055
+ [name2]: { command: "npx", args: ["-y", "@portel/photon", "mcp", name2] }
23056
+ }
23057
+ };
23058
+ }
23059
+ } else {
23060
+ config3 = {
23061
+ mcpServers: { [name2]: { command: "npx", args: ["-y", "@portel/photon", "mcp", name2] } }
23062
+ };
22910
23063
  }
22911
- );
22912
- if (!res.ok) throw new Error("Failed to fetch config");
22913
- const config3 = await res.json();
23064
+ }
22914
23065
  await navigator.clipboard.writeText(JSON.stringify(config3, null, 2));
22915
- showToast("MCP config copied \u2014 paste into Claude Desktop settings", "success");
23066
+ const label = transport === "url" ? "HTTP config" : "Claude Desktop config";
23067
+ showToast(`${label} copied to clipboard`, "success");
22916
23068
  } catch (error2) {
22917
23069
  console.warn("Copy MCP config failed:", error2);
22918
- showToast("Failed to copy MCP config", "error");
23070
+ showToast("Failed to copy config", "error");
22919
23071
  }
22920
23072
  };
22921
23073
  this._handleUpgrade = async () => {
@@ -23124,6 +23276,7 @@ var BeamApp = class extends i4 {
23124
23276
  return;
23125
23277
  }
23126
23278
  const isEditable = this._selectedPhoton?.editable && !this._selectedPhoton?.isExternalMCP;
23279
+ this._mainTab = "source";
23127
23280
  if (isEditable) {
23128
23281
  this._view = "studio";
23129
23282
  } else {
@@ -23280,7 +23433,7 @@ var BeamApp = class extends i4 {
23280
23433
  };
23281
23434
  this._handleDeletePhoton = async () => {
23282
23435
  this._closeSettingsMenu();
23283
- if (await confirmDialog(`Remove "${this._selectedPhoton?.name}"? It will be moved to trash.`, {
23436
+ if (await confirmElicit(`Remove "${this._selectedPhoton?.name}"? It will be moved to trash.`, {
23284
23437
  confirm: "Remove",
23285
23438
  destructive: true
23286
23439
  })) {
@@ -23466,22 +23619,35 @@ var BeamApp = class extends i4 {
23466
23619
  this._broadcastThemeToIframes();
23467
23620
  };
23468
23621
  this._handleOklchThemeReset = () => {
23469
- this._oklchEnabled = false;
23470
- const cssVars = beamThemeToCSS(
23622
+ const oldVars = beamThemeToCSS(
23471
23623
  generateBeamThemeColors({ hue: 0, chroma: 0, lightness: 0.5, theme: "dark" })
23472
23624
  );
23473
- for (const prop of Object.keys(cssVars)) {
23625
+ for (const prop of Object.keys(oldVars)) {
23474
23626
  this.style.removeProperty(prop);
23475
23627
  }
23476
- this._applyTheme();
23628
+ const theme3 = this._theme || "dark";
23629
+ const defaultViolet = { hue: 260, chroma: 0.15, lightness: 0.65, theme: theme3 };
23630
+ this._oklchEnabled = true;
23631
+ this._applyOklchTheme(defaultViolet);
23477
23632
  this._broadcastThemeToIframes();
23478
23633
  showToast("Theme reset to default", "info");
23479
23634
  };
23635
+ this._handleLocalElicit = (e8) => {
23636
+ const { data, resolve: resolve2 } = e8.detail;
23637
+ this._localElicitResolve = resolve2;
23638
+ this._elicitationData = { ...data };
23639
+ this._showElicitation = true;
23640
+ };
23480
23641
  this._handleElicitationSubmit = async (e8) => {
23481
23642
  const { value } = e8.detail;
23482
23643
  const elicitationId = this._elicitationData?.elicitationId;
23483
23644
  this._showElicitation = false;
23484
23645
  this._elicitationData = null;
23646
+ if (this._localElicitResolve) {
23647
+ this._localElicitResolve({ action: "accept", value });
23648
+ this._localElicitResolve = void 0;
23649
+ return;
23650
+ }
23485
23651
  const pendingWindow = elicitationId ? this._pendingBridgeCalls.get(elicitationId) : null;
23486
23652
  if (pendingWindow) {
23487
23653
  this._pendingBridgeCalls.delete(elicitationId);
@@ -23508,6 +23674,11 @@ var BeamApp = class extends i4 {
23508
23674
  this._showElicitation = false;
23509
23675
  this._elicitationData = null;
23510
23676
  this._isExecuting = false;
23677
+ if (this._localElicitResolve) {
23678
+ this._localElicitResolve({ action: "cancel" });
23679
+ this._localElicitResolve = void 0;
23680
+ return;
23681
+ }
23511
23682
  const pendingWindow = elicitationId ? this._pendingBridgeCalls.get(elicitationId) : null;
23512
23683
  if (pendingWindow) {
23513
23684
  this._pendingBridgeCalls.delete(elicitationId);
@@ -23523,6 +23694,18 @@ var BeamApp = class extends i4 {
23523
23694
  this._log("info", "Input cancelled");
23524
23695
  showToast("Input cancelled", "info");
23525
23696
  };
23697
+ this._handleApprovalResponse = async (e8) => {
23698
+ const { approvalId, photon, approved } = e8.detail;
23699
+ this._pendingApprovalsList = this._pendingApprovalsList.filter((a5) => a5.id !== approvalId);
23700
+ if (this._pendingApprovalsList.length === 0) {
23701
+ this._showApprovals = false;
23702
+ }
23703
+ const result = await mcpClient.sendApprovalResponse(approvalId, photon, approved);
23704
+ if (!result.success) {
23705
+ showToast("Failed to send approval response", "error");
23706
+ void this._fetchPendingApprovals();
23707
+ }
23708
+ };
23526
23709
  this._handleOAuthComplete = async (e8) => {
23527
23710
  const { elicitationId, success: success2 } = e8.detail;
23528
23711
  this._showElicitation = false;
@@ -23755,7 +23938,7 @@ var BeamApp = class extends i4 {
23755
23938
  this._handleReconfigure();
23756
23939
  break;
23757
23940
  case "copy-config":
23758
- void this._handleCopyMCPConfig();
23941
+ void this._copyConfigSnippet("stdio");
23759
23942
  break;
23760
23943
  case "upgrade":
23761
23944
  void this._handleUpgrade();
@@ -24047,6 +24230,28 @@ var BeamApp = class extends i4 {
24047
24230
  this._showError("Photon not found", `Method '${action}' not found on ${targetName}`);
24048
24231
  }
24049
24232
  }
24233
+ async _handleCreatePhoton(filename, template = "blank") {
24234
+ try {
24235
+ const res = await fetch("/api/create-photon", {
24236
+ method: "POST",
24237
+ headers: { "Content-Type": "application/json" },
24238
+ body: JSON.stringify({ filename, template })
24239
+ });
24240
+ if (!res.ok) {
24241
+ const err = await res.json().catch(() => ({ error: "Failed to create photon" }));
24242
+ this._showError("Create failed", err.error);
24243
+ return;
24244
+ }
24245
+ const { name: name2 } = await res.json();
24246
+ showToast(`Created ${filename}`, "success");
24247
+ this._pendingStudioOpen = true;
24248
+ setTimeout(() => {
24249
+ this._sidebar?.scrollPhotonIntoView(name2);
24250
+ }, 1500);
24251
+ } catch (err) {
24252
+ this._showError("Create failed", err.message);
24253
+ }
24254
+ }
24050
24255
  /**
24051
24256
  * Collect static methods from all internal photons for global display
24052
24257
  */
@@ -24130,6 +24335,7 @@ var BeamApp = class extends i4 {
24130
24335
  this._verboseLogging = true;
24131
24336
  }
24132
24337
  document.addEventListener("click", this._handleDocumentClick);
24338
+ document.addEventListener("beam:elicit-local", this._handleLocalElicit);
24133
24339
  void this._connectMCP();
24134
24340
  this._setupNotificationHandlers();
24135
24341
  window.addEventListener("popstate", this._handleRouteChange);
@@ -24174,6 +24380,7 @@ var BeamApp = class extends i4 {
24174
24380
  window.removeEventListener("message", this._handleBridgeMessage);
24175
24381
  window.removeEventListener("keydown", this._handleKeydown);
24176
24382
  document.removeEventListener("click", this._handleDocumentClick);
24383
+ document.removeEventListener("beam:elicit-local", this._handleLocalElicit);
24177
24384
  this._cleanupCollectionSubscriptions();
24178
24385
  }
24179
24386
  willUpdate(changedProperties) {
@@ -24297,6 +24504,7 @@ var BeamApp = class extends i4 {
24297
24504
  }
24298
24505
  this._initialConnectDone = true;
24299
24506
  void this._checkForUpdates();
24507
+ this._startApprovalsPolling();
24300
24508
  if (window.location.pathname !== "/") {
24301
24509
  void this._handleRouteChange();
24302
24510
  } else if (!this._selectedPhoton && this._photons.length > 0) {
@@ -24323,6 +24531,7 @@ var BeamApp = class extends i4 {
24323
24531
  this._connected = false;
24324
24532
  this._reconnecting = true;
24325
24533
  this._reconnectAttempt++;
24534
+ this._stopApprovalsPolling();
24326
24535
  showToast("Connection lost. Reconnecting...", "warning");
24327
24536
  });
24328
24537
  mcpClient.on("tools-changed", () => {
@@ -24481,6 +24690,31 @@ var BeamApp = class extends i4 {
24481
24690
  this._photons = data.photons.map(
24482
24691
  (p5) => updateFlags.has(p5.name) ? { ...p5, hasUpdate: true } : p5
24483
24692
  );
24693
+ if (this._pendingStudioOpen) {
24694
+ const newPhoton = this._photons.find((p5) => !p5.internal && !prevNames.has(p5.name));
24695
+ if (newPhoton) {
24696
+ this._pendingStudioOpen = false;
24697
+ this._selectedPhoton = newPhoton;
24698
+ this._view = "studio";
24699
+ if (this._pendingTemplateSource) {
24700
+ const tpl = this._pendingTemplateSource;
24701
+ this._pendingTemplateSource = void 0;
24702
+ requestAnimationFrame(() => {
24703
+ const studio = this.shadowRoot?.querySelector("photon-studio");
24704
+ if (studio?.applyTemplate) {
24705
+ studio.applyTemplate({
24706
+ source: tpl,
24707
+ id: "custom",
24708
+ name: "",
24709
+ description: "",
24710
+ icon: ""
24711
+ });
24712
+ }
24713
+ });
24714
+ }
24715
+ this._updateRoute(true);
24716
+ }
24717
+ }
24484
24718
  if (this._selectedPhoton) {
24485
24719
  const updated = this._photons.find((p5) => p5.name === this._selectedPhoton?.name);
24486
24720
  if (updated) {
@@ -24494,28 +24728,7 @@ var BeamApp = class extends i4 {
24494
24728
  if (newUserPhoton) {
24495
24729
  this._selectedPhoton = newUserPhoton;
24496
24730
  this._welcomePhase = "welcome";
24497
- if (this._pendingStudioOpen) {
24498
- this._pendingStudioOpen = false;
24499
- this._view = "studio";
24500
- if (this._pendingTemplateSource) {
24501
- const tpl = this._pendingTemplateSource;
24502
- this._pendingTemplateSource = void 0;
24503
- requestAnimationFrame(() => {
24504
- const studio = this.shadowRoot?.querySelector("photon-studio");
24505
- if (studio?.applyTemplate) {
24506
- studio.applyTemplate({
24507
- source: tpl,
24508
- id: "custom",
24509
- name: "",
24510
- description: "",
24511
- icon: ""
24512
- });
24513
- }
24514
- });
24515
- }
24516
- } else {
24517
- this._view = "list";
24518
- }
24731
+ this._view = "list";
24519
24732
  this._updateRoute(true);
24520
24733
  }
24521
24734
  }
@@ -24584,6 +24797,26 @@ var BeamApp = class extends i4 {
24584
24797
  this._log("info", `Input required: ${data.message || elicitationData.ask}`);
24585
24798
  }
24586
24799
  });
24800
+ mcpClient.on("elicitation-deferred", (data) => {
24801
+ if (data) {
24802
+ if (this._elicitationData && this._elicitationData.elicitationId === data.elicitationId) {
24803
+ this._showElicitation = false;
24804
+ this._elicitationData = null;
24805
+ }
24806
+ void this._fetchPendingApprovals();
24807
+ this._log("info", `Moved to pending approvals: ${data.message || "Approval required"}`);
24808
+ }
24809
+ });
24810
+ mcpClient.on("approval-resolved", (data) => {
24811
+ if (data) {
24812
+ this._pendingApprovalsList = this._pendingApprovalsList.filter(
24813
+ (a5) => a5.id !== data.approvalId
24814
+ );
24815
+ if (this._pendingApprovalsList.length === 0) {
24816
+ this._showApprovals = false;
24817
+ }
24818
+ }
24819
+ });
24587
24820
  mcpClient.on("channel-event", (data) => {
24588
24821
  this._forwardToIframes({
24589
24822
  jsonrpc: "2.0",
@@ -25097,6 +25330,7 @@ var BeamApp = class extends i4 {
25097
25330
  .connected=${this._connected}
25098
25331
  .reconnecting=${this._reconnecting}
25099
25332
  .updatesAvailable=${this._updatesAvailable.length}
25333
+ .pendingApprovals=${this._pendingApprovalsList.length}
25100
25334
  .mainTab=${this._mainTab}
25101
25335
  .isApp=${!!(this._selectedPhoton?.isApp || this._selectedPhoton?.isExternalMCP && this._selectedPhoton?.hasMcpApp)}
25102
25336
  .hasSettings=${!!(this._selectedPhoton?.hasSettings && !this._selectedPhoton?.isExternalMCP)}
@@ -25154,12 +25388,19 @@ var BeamApp = class extends i4 {
25154
25388
  @theme-change=${this._handleThemeChange}
25155
25389
  @open-theme-settings=${() => this._showThemeSettings = true}
25156
25390
  @show-shortcuts=${this._showHelpModal}
25391
+ @show-approvals=${() => {
25392
+ this._showApprovals = true;
25393
+ void this._fetchPendingApprovals();
25394
+ }}
25157
25395
  @reconnect-mcp=${(e8) => {
25158
25396
  void this._handleReconnectMCP(e8);
25159
25397
  }}
25160
25398
  @diagnostics=${() => {
25161
25399
  this._view = "diagnostics";
25162
25400
  this._updateRoute();
25401
+ }}
25402
+ @create-photon=${(e8) => {
25403
+ void this._handleCreatePhoton(e8.detail.name, e8.detail.template);
25163
25404
  }}
25164
25405
  @open-studio=${(e8) => {
25165
25406
  const photon = this._photons.find((p5) => p5.name === e8.detail.photonName);
@@ -25230,7 +25471,7 @@ var BeamApp = class extends i4 {
25230
25471
  ${collapse}
25231
25472
  </button>
25232
25473
  </div>` : ""}
25233
- ${this._selectedPhoton && !this._selectedMethod && this._mainTab === "methods" ? b2`<div class="main-toolbar">
25474
+ ${this._selectedPhoton && !this._selectedMethod && this._mainTab === "methods" && this._view !== "studio" ? b2`<div class="main-toolbar">
25234
25475
  <div style="flex: 1; min-width: 0;">${this._renderPhotonToolbar()}</div>
25235
25476
  </div>` : ""}
25236
25477
  ${this._mainTab === "log" ? b2`<activity-log
@@ -25281,6 +25522,17 @@ var BeamApp = class extends i4 {
25281
25522
  @cancel=${this._handleElicitationCancel}
25282
25523
  @oauth-complete=${this._handleOAuthComplete}
25283
25524
  ></elicitation-modal>
25525
+
25526
+ ${this._showApprovals ? b2`
25527
+ <div class="approvals-overlay" @click=${() => this._showApprovals = false}></div>
25528
+ <div class="approvals-panel glass-panel">
25529
+ <pending-approvals
25530
+ .approvals=${this._pendingApprovalsList}
25531
+ @approval-response=${this._handleApprovalResponse}
25532
+ @close=${() => this._showApprovals = false}
25533
+ ></pending-approvals>
25534
+ </div>
25535
+ ` : ""}
25284
25536
  `;
25285
25537
  }
25286
25538
  _renderMethodsBentoOnly() {
@@ -25328,6 +25580,7 @@ var BeamApp = class extends i4 {
25328
25580
  return b2`<photon-studio
25329
25581
  .photonName=${this._selectedPhoton?.name || ""}
25330
25582
  .theme=${this._theme}
25583
+ .hideCloseButton=${true}
25331
25584
  @studio-close=${() => this._view = "list"}
25332
25585
  @studio-saved=${async () => {
25333
25586
  const tools = await mcpClient.listTools();
@@ -27037,6 +27290,12 @@ ${photon.errorMessage || "Unknown error"}</pre
27037
27290
  case "run-tests":
27038
27291
  void this._runTests();
27039
27292
  break;
27293
+ case "copy-config-stdio":
27294
+ void this._copyConfigSnippet("stdio");
27295
+ break;
27296
+ case "copy-config-url":
27297
+ void this._copyConfigSnippet("url");
27298
+ break;
27040
27299
  case "help":
27041
27300
  this._mainTab = "help";
27042
27301
  void this._loadPhotonHelp();
@@ -27175,7 +27434,7 @@ ${photon.errorMessage || "Unknown error"}</pre
27175
27434
  }
27176
27435
  async _handleBackFromMethod() {
27177
27436
  const form = this.shadowRoot?.querySelector("invoke-form");
27178
- if (form?.isDirty && !await confirmDialog("You have unsaved changes. Discard them?", {
27437
+ if (form?.isDirty && !await confirmElicit("You have unsaved changes. Discard them?", {
27179
27438
  confirm: "Discard",
27180
27439
  destructive: true
27181
27440
  })) {
@@ -27622,6 +27881,21 @@ ${photon.errorMessage || "Unknown error"}</pre
27622
27881
  this.style.setProperty(prop, value);
27623
27882
  }
27624
27883
  }
27884
+ async _fetchPendingApprovals() {
27885
+ if (!this._mcpReady) return;
27886
+ this._pendingApprovalsList = await mcpClient.fetchPendingApprovals();
27887
+ }
27888
+ _startApprovalsPolling() {
27889
+ this._stopApprovalsPolling();
27890
+ void this._fetchPendingApprovals();
27891
+ this._approvalsRefreshInterval = setInterval(() => void this._fetchPendingApprovals(), 6e4);
27892
+ }
27893
+ _stopApprovalsPolling() {
27894
+ if (this._approvalsRefreshInterval) {
27895
+ clearInterval(this._approvalsRefreshInterval);
27896
+ this._approvalsRefreshInterval = void 0;
27897
+ }
27898
+ }
27625
27899
  _applyTheme() {
27626
27900
  this.setAttribute("data-theme", this._theme);
27627
27901
  }
@@ -27989,6 +28263,17 @@ ${photon.errorMessage || "Unknown error"}</pre
27989
28263
  toggle: true,
27990
28264
  toggleActive: this._verboseLogging
27991
28265
  });
28266
+ items.push({
28267
+ id: "copy-config-stdio",
28268
+ label: "Copy Config (Claude Desktop)",
28269
+ iconSvg: iconSvgString(iconPaths.clone),
28270
+ dividerBefore: true
28271
+ });
28272
+ items.push({
28273
+ id: "copy-config-url",
28274
+ label: "Copy Config (HTTP)",
28275
+ iconSvg: iconSvgString(iconPaths.clone)
28276
+ });
27992
28277
  if (showInstallApp) {
27993
28278
  items.push({
27994
28279
  id: "install-app",
@@ -30540,7 +30825,8 @@ BeamApp.styles = [
30540
30825
  }
30541
30826
 
30542
30827
  /* ===== Theme Settings Panel ===== */
30543
- .theme-settings-overlay {
30828
+ .theme-settings-overlay,
30829
+ .approvals-overlay {
30544
30830
  position: fixed;
30545
30831
  inset: 0;
30546
30832
  background: rgba(0, 0, 0, 0.3);
@@ -30559,6 +30845,29 @@ BeamApp.styles = [
30559
30845
  animation: slideInRight 0.2s ease;
30560
30846
  }
30561
30847
 
30848
+ .approvals-panel {
30849
+ position: fixed;
30850
+ bottom: var(--space-xl);
30851
+ left: var(--space-md);
30852
+ width: 340px;
30853
+ max-height: 60vh;
30854
+ z-index: 1001;
30855
+ overflow-y: auto;
30856
+ border-radius: var(--radius-md);
30857
+ animation: slideInUp 0.2s ease;
30858
+ }
30859
+
30860
+ @keyframes slideInUp {
30861
+ from {
30862
+ transform: translateY(20px);
30863
+ opacity: 0;
30864
+ }
30865
+ to {
30866
+ transform: translateY(0);
30867
+ opacity: 1;
30868
+ }
30869
+ }
30870
+
30562
30871
  @keyframes slideInRight {
30563
30872
  from {
30564
30873
  transform: translateX(20px);
@@ -30988,6 +31297,12 @@ __decorateClass([
30988
31297
  __decorateClass([
30989
31298
  r5()
30990
31299
  ], BeamApp.prototype, "_showElicitation", 2);
31300
+ __decorateClass([
31301
+ r5()
31302
+ ], BeamApp.prototype, "_showApprovals", 2);
31303
+ __decorateClass([
31304
+ r5()
31305
+ ], BeamApp.prototype, "_pendingApprovalsList", 2);
30991
31306
  __decorateClass([
30992
31307
  r5()
30993
31308
  ], BeamApp.prototype, "_protocolMode", 2);
@@ -31121,7 +31436,12 @@ var BeamSidebar = class extends i4 {
31121
31436
  this._showFavoritesOnly = false;
31122
31437
  this._favorites = /* @__PURE__ */ new Set();
31123
31438
  this._collapsedSections = /* @__PURE__ */ new Set();
31439
+ /** Live recency list — saved to localStorage but NOT used for rendering.
31440
+ * Only applied on next page load via _initialRecentOrder. */
31124
31441
  this._recentPhotons = [];
31442
+ /** Snapshot of recency order captured at page load — used for sorting.
31443
+ * Stays stable during the session so the sidebar doesn't jump around. */
31444
+ this._initialRecentOrder = [];
31125
31445
  this._notificationWarmth = /* @__PURE__ */ new Map();
31126
31446
  }
31127
31447
  connectedCallback() {
@@ -31144,7 +31464,10 @@ var BeamSidebar = class extends i4 {
31144
31464
  _loadRecent() {
31145
31465
  try {
31146
31466
  const stored = localStorage.getItem(BeamSidebar.RECENT_KEY);
31147
- if (stored) this._recentPhotons = JSON.parse(stored);
31467
+ if (stored) {
31468
+ this._recentPhotons = JSON.parse(stored);
31469
+ this._initialRecentOrder = [...this._recentPhotons];
31470
+ }
31148
31471
  } catch {
31149
31472
  }
31150
31473
  }
@@ -31251,9 +31574,10 @@ var BeamSidebar = class extends i4 {
31251
31574
  get _nonAppExternalMCPs() {
31252
31575
  return this._filteredExternalMCPs.filter((m3) => !m3.hasMcpApp);
31253
31576
  }
31254
- /** Sort items by recency — recently used items float to the top */
31577
+ /** Sort items by recency — uses the order snapshot from page load,
31578
+ * so the list stays stable during the session and only reorders on refresh. */
31255
31579
  _sortByRecency(items) {
31256
- const recentIndex = new Map(this._recentPhotons.map((name2, i7) => [name2, i7]));
31580
+ const recentIndex = new Map(this._initialRecentOrder.map((name2, i7) => [name2, i7]));
31257
31581
  return [...items].sort((a5, b3) => {
31258
31582
  const aIdx = recentIndex.get(a5.name);
31259
31583
  const bIdx = recentIndex.get(b3.name);
@@ -31289,11 +31613,11 @@ var BeamSidebar = class extends i4 {
31289
31613
  <button
31290
31614
  class="sidebar-minimize-btn"
31291
31615
  @click=${() => this.dispatchEvent(new CustomEvent("toggle-focus"))}
31292
- title="Minimize sidebar"
31616
+ title="Hide sidebar"
31293
31617
  >
31294
31618
  <svg
31295
- width="14"
31296
- height="14"
31619
+ width="18"
31620
+ height="18"
31297
31621
  viewBox="0 0 24 24"
31298
31622
  fill="none"
31299
31623
  stroke="currentColor"
@@ -31301,20 +31625,31 @@ var BeamSidebar = class extends i4 {
31301
31625
  stroke-linecap="round"
31302
31626
  stroke-linejoin="round"
31303
31627
  >
31304
- <path d="M11 19H4a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h5" />
31305
- <polyline points="13 15 9 12 13 9" />
31628
+ <rect width="18" height="18" x="3" y="3" rx="2" />
31629
+ <path d="M9 3v18" />
31630
+ <path d="m16 15-3-3 3-3" />
31306
31631
  </svg>
31307
31632
  </button>
31308
31633
  </div>
31309
- <div class="search-box" role="search">
31310
- <input
31311
- type="search"
31312
- placeholder="Search photons... (⌘K)"
31313
- .value=${this._searchQuery}
31314
- @input=${(e8) => this._handleSearch(e8)}
31315
- @keydown=${(e8) => this._handleSearchKeydown(e8)}
31316
- aria-label="Search photons"
31317
- />
31634
+ <div class="search-row">
31635
+ <div class="search-box" role="search">
31636
+ <input
31637
+ type="search"
31638
+ placeholder="Search photons... (⌘K)"
31639
+ .value=${this._searchQuery}
31640
+ @input=${(e8) => this._handleSearch(e8)}
31641
+ @keydown=${(e8) => this._handleSearchKeydown(e8)}
31642
+ aria-label="Search photons"
31643
+ />
31644
+ </div>
31645
+ <button
31646
+ class="sidebar-minimize-btn create-btn"
31647
+ @click=${() => this._createPhoton()}
31648
+ title="Create new photon"
31649
+ aria-label="Create new photon"
31650
+ >
31651
+ ${plus}
31652
+ </button>
31318
31653
  </div>
31319
31654
  <div class="filter-row" role="group" aria-label="Filter options">
31320
31655
  <button
@@ -31409,19 +31744,18 @@ var BeamSidebar = class extends i4 {
31409
31744
  </nav>
31410
31745
 
31411
31746
  <div class="sidebar-footer">
31412
- ${this.pendingApprovals > 0 ? b2`
31413
- <button
31414
- class="footer-link approval-badge-btn"
31415
- @click=${() => this.dispatchEvent(
31747
+ <button
31748
+ class="footer-link approval-badge-btn ${this.pendingApprovals === 0 ? "disabled" : ""}"
31749
+ @click=${() => this.pendingApprovals > 0 && this.dispatchEvent(
31416
31750
  new CustomEvent("show-approvals", { bubbles: true, composed: true })
31417
31751
  )}
31418
- title="Pending approvals (${this.pendingApprovals})"
31419
- aria-label="Show pending approvals"
31420
- >
31421
- ${shieldCheck}
31422
- <span class="approval-badge">${this.pendingApprovals}</span>
31423
- </button>
31424
- ` : ""}
31752
+ title="${this.pendingApprovals > 0 ? `Pending approvals (${this.pendingApprovals})` : "No pending approvals"}"
31753
+ aria-label="Show pending approvals"
31754
+ ?disabled=${this.pendingApprovals === 0}
31755
+ >
31756
+ ${shieldCheck}
31757
+ <span class="approval-badge">${this.pendingApprovals}</span>
31758
+ </button>
31425
31759
  <button
31426
31760
  class="footer-link"
31427
31761
  @click=${() => this._showShortcuts()}
@@ -31456,6 +31790,41 @@ var BeamSidebar = class extends i4 {
31456
31790
  _showShortcuts() {
31457
31791
  this.dispatchEvent(new CustomEvent("show-shortcuts", { bubbles: true, composed: true }));
31458
31792
  }
31793
+ async _createPhoton() {
31794
+ const result = await elicit({
31795
+ ask: "form",
31796
+ icon: "\u2728",
31797
+ message: "Create a new photon",
31798
+ description: "Give your photon a name and we\u2019ll set up everything for you. Use lowercase letters and hyphens \u2014 like my-api or weather-bot.",
31799
+ submitLabel: "Create",
31800
+ cancelLabel: "Cancel",
31801
+ fields: [
31802
+ { name: "name", label: "Name", placeholder: "e.g. my-api", required: true },
31803
+ {
31804
+ name: "template",
31805
+ label: "Template",
31806
+ type: "text",
31807
+ enum: ["Hello World", "API Tool", "Stateful", "App"],
31808
+ default: "Hello World"
31809
+ }
31810
+ ]
31811
+ });
31812
+ if (result.action === "cancel") return;
31813
+ const form = result.value;
31814
+ if (!form?.name?.trim()) return;
31815
+ let filename = form.name.trim().toLowerCase().replace(/[^a-z0-9.-]/g, "-");
31816
+ if (!filename.endsWith(".photon.ts")) {
31817
+ filename = filename.replace(/\.photon$/, "") + ".photon.ts";
31818
+ }
31819
+ const template = (form.template || "Blank").toLowerCase().replace(/\s+/g, "-");
31820
+ this.dispatchEvent(
31821
+ new CustomEvent("create-photon", {
31822
+ detail: { name: filename, template },
31823
+ bubbles: true,
31824
+ composed: true
31825
+ })
31826
+ );
31827
+ }
31459
31828
  _openStudio(photonName) {
31460
31829
  this.dispatchEvent(
31461
31830
  new CustomEvent("open-studio", {
@@ -31534,15 +31903,15 @@ var BeamSidebar = class extends i4 {
31534
31903
  title="${photon.description || photon.name}${photon.path ? `
31535
31904
  ${photon.path}` : ""}"
31536
31905
  >
31906
+ <div
31907
+ class="photon-icon ${isEmoji ? "emoji-icon" : ""}"
31908
+ style="${initialsStyle}"
31909
+ aria-hidden="true"
31910
+ >
31911
+ ${displayIcon}
31912
+ </div>
31537
31913
  <div class="photon-item-body">
31538
31914
  <div class="photon-main-row">
31539
- <div
31540
- class="photon-icon ${isEmoji ? "emoji-icon" : ""}"
31541
- style="${initialsStyle}"
31542
- aria-hidden="true"
31543
- >
31544
- ${displayIcon}
31545
- </div>
31546
31915
  <div class="photon-info">
31547
31916
  <div class="photon-name">${photon.name}</div>
31548
31917
  ${photon.internal ? b2`<span class="internal-badge">System</span>` : ""}
@@ -31582,9 +31951,9 @@ ${photon.path}` : ""}"
31582
31951
  title="${mcp.description || "External MCP server"}${mcp.errorMessage ? `
31583
31952
  \u26A0\uFE0F ${mcp.errorMessage}` : ""}"
31584
31953
  >
31954
+ <div class="photon-icon external-mcp-icon" aria-hidden="true">${displayIcon}</div>
31585
31955
  <div class="photon-item-body">
31586
31956
  <div class="photon-main-row">
31587
- <div class="photon-icon external-mcp-icon" aria-hidden="true">${displayIcon}</div>
31588
31957
  <div class="photon-info">
31589
31958
  <div class="photon-name">${mcp.name}</div>
31590
31959
  </div>
@@ -31980,32 +32349,32 @@ BeamSidebar.styles = [
31980
32349
  }
31981
32350
 
31982
32351
  .status-indicator {
31983
- width: 8px;
31984
- height: 8px;
32352
+ width: 9px;
32353
+ height: 9px;
31985
32354
  border-radius: 50%;
31986
32355
  flex-shrink: 0;
31987
32356
  }
31988
32357
 
31989
32358
  .status-indicator.connected {
31990
- background: var(--color-success);
32359
+ background: #22dd44;
31991
32360
  box-shadow:
31992
- 0 0 4px 1px var(--color-success-glow),
31993
- 0 0 8px 2px var(--color-success-glow);
32361
+ 0 0 4px 2px rgba(34, 221, 68, 0.6),
32362
+ 0 0 10px 4px rgba(34, 221, 68, 0.3);
31994
32363
  }
31995
32364
 
31996
32365
  .status-indicator.reconnecting {
31997
- background: var(--color-warning);
32366
+ background: #ffbb33;
31998
32367
  box-shadow:
31999
- 0 0 4px 1px var(--color-warning-glow),
32000
- 0 0 8px 2px var(--color-warning-glow);
32368
+ 0 0 4px 2px rgba(255, 187, 51, 0.6),
32369
+ 0 0 10px 4px rgba(255, 187, 51, 0.3);
32001
32370
  animation: pulse 1s ease-in-out infinite;
32002
32371
  }
32003
32372
 
32004
32373
  .status-indicator.disconnected {
32005
- background: var(--color-error);
32374
+ background: #ff4444;
32006
32375
  box-shadow:
32007
- 0 0 4px 1px rgba(248, 113, 113, 0.5),
32008
- 0 0 8px 2px rgba(248, 113, 113, 0.3);
32376
+ 0 0 4px 2px rgba(255, 68, 68, 0.6),
32377
+ 0 0 10px 4px rgba(255, 68, 68, 0.3);
32009
32378
  }
32010
32379
 
32011
32380
  @keyframes pulse {
@@ -32056,17 +32425,29 @@ BeamSidebar.styles = [
32056
32425
  background: var(--bg-glass-strong);
32057
32426
  }
32058
32427
 
32059
- .search-box {
32428
+ .search-row {
32429
+ display: flex;
32430
+ align-items: center;
32431
+ gap: var(--space-xs);
32060
32432
  margin-top: var(--space-md);
32433
+ }
32434
+
32435
+ .search-box {
32436
+ flex: 1;
32061
32437
  position: relative;
32062
32438
  }
32063
32439
 
32440
+ .create-btn {
32441
+ flex-shrink: 0;
32442
+ margin-top: 0 !important;
32443
+ }
32444
+
32064
32445
  .sidebar-minimize-btn {
32065
- width: 28px;
32066
- height: 28px;
32446
+ width: 32px;
32447
+ height: 32px;
32067
32448
  border-radius: var(--radius-sm);
32068
- background: transparent;
32069
- border: none;
32449
+ background: var(--bg-glass);
32450
+ border: 1px solid var(--border-glass);
32070
32451
  color: var(--t-muted);
32071
32452
  cursor: pointer;
32072
32453
  display: flex;
@@ -32079,7 +32460,8 @@ BeamSidebar.styles = [
32079
32460
 
32080
32461
  .sidebar-minimize-btn:hover {
32081
32462
  color: var(--t-primary);
32082
- background: var(--bg-glass);
32463
+ background: var(--bg-glass-strong);
32464
+ border-color: color-mix(in srgb, var(--accent-primary) 30%, var(--border-glass));
32083
32465
  }
32084
32466
 
32085
32467
  input {
@@ -32088,15 +32470,16 @@ BeamSidebar.styles = [
32088
32470
 
32089
32471
  .section-header {
32090
32472
  font-family: var(--font-display);
32091
- padding: var(--space-sm) var(--space-md);
32092
- font-size: var(--text-xs);
32473
+ padding: var(--space-xs) var(--space-md);
32474
+ font-size: 10px;
32093
32475
  font-weight: 600;
32094
32476
  text-transform: uppercase;
32095
- letter-spacing: 0.1em;
32477
+ letter-spacing: 0.12em;
32096
32478
  color: var(--t-muted);
32097
- margin-top: var(--space-sm);
32098
- border-left: 2px solid var(--accent-primary);
32099
- background: var(--bg-glass-strong);
32479
+ opacity: 0.75;
32480
+ margin-top: var(--space-md);
32481
+ border-left: none;
32482
+ background: color-mix(in srgb, var(--t-muted) 8%, transparent);
32100
32483
  cursor: pointer;
32101
32484
  user-select: none;
32102
32485
  display: flex;
@@ -32105,18 +32488,17 @@ BeamSidebar.styles = [
32105
32488
  }
32106
32489
 
32107
32490
  .section-header:hover {
32491
+ opacity: 1;
32108
32492
  color: var(--t-primary);
32109
- background: var(--bg-panel);
32110
32493
  }
32111
32494
 
32112
32495
  .section-header.attention {
32113
32496
  color: var(--color-warning);
32114
- border-left-color: var(--color-warning);
32115
32497
  }
32116
32498
 
32117
32499
  .section-header.attention:hover {
32118
32500
  color: var(--color-warning);
32119
- opacity: 0.85;
32501
+ opacity: 1;
32120
32502
  }
32121
32503
 
32122
32504
  .section-label {
@@ -32175,12 +32557,12 @@ BeamSidebar.styles = [
32175
32557
  border-left: 2px solid var(--accent-primary);
32176
32558
  color: var(--accent-primary);
32177
32559
  font-weight: 500;
32178
- align-items: stretch;
32560
+ align-items: center;
32179
32561
  padding-top: calc(var(--space-sm) + 2px);
32180
32562
  padding-bottom: calc(var(--space-sm) + 2px);
32181
32563
  }
32182
32564
 
32183
- .photon-item.flash-highlight {
32565
+ .photon-item.flash-highlight:not(.active) {
32184
32566
  animation: flash-highlight 0.6s ease-out;
32185
32567
  }
32186
32568
 
@@ -32193,7 +32575,7 @@ BeamSidebar.styles = [
32193
32575
  }
32194
32576
  }
32195
32577
 
32196
- .photon-item.warmth {
32578
+ .photon-item.warmth:not(.active) {
32197
32579
  animation: warmth-fade 5s ease-out forwards;
32198
32580
  }
32199
32581
 
@@ -32219,6 +32601,10 @@ BeamSidebar.styles = [
32219
32601
  color: var(--t-primary);
32220
32602
  flex-shrink: 0;
32221
32603
  letter-spacing: 0.5px;
32604
+ transition:
32605
+ width 0.25s ease,
32606
+ height 0.25s ease,
32607
+ font-size 0.25s ease;
32222
32608
  }
32223
32609
 
32224
32610
  .photon-icon.emoji-icon {
@@ -32227,6 +32613,17 @@ BeamSidebar.styles = [
32227
32613
  overflow: hidden;
32228
32614
  }
32229
32615
 
32616
+ /* Scale icon up when the row is expanded with view tabs */
32617
+ .photon-item.active .photon-icon {
32618
+ width: 42px;
32619
+ height: 42px;
32620
+ font-size: 15px;
32621
+ }
32622
+
32623
+ .photon-item.active .photon-icon.emoji-icon {
32624
+ font-size: 30px;
32625
+ }
32626
+
32230
32627
  .photon-item.internal {
32231
32628
  opacity: 0.85;
32232
32629
  }
@@ -32286,7 +32683,6 @@ BeamSidebar.styles = [
32286
32683
  display: flex;
32287
32684
  align-items: center;
32288
32685
  gap: 4px;
32289
- margin-left: calc(28px + var(--space-sm));
32290
32686
  }
32291
32687
 
32292
32688
  .photon-view-tab {
@@ -32422,6 +32818,16 @@ BeamSidebar.styles = [
32422
32818
  position: relative;
32423
32819
  }
32424
32820
 
32821
+ .approval-badge-btn.disabled {
32822
+ opacity: 0.4;
32823
+ cursor: default;
32824
+ }
32825
+
32826
+ .approval-badge-btn.disabled:hover {
32827
+ color: var(--t-muted);
32828
+ background: none;
32829
+ }
32830
+
32425
32831
  .approval-badge {
32426
32832
  position: absolute;
32427
32833
  top: -2px;
@@ -32709,9 +33115,6 @@ __decorateClass([
32709
33115
  __decorateClass([
32710
33116
  r5()
32711
33117
  ], BeamSidebar.prototype, "_collapsedSections", 2);
32712
- __decorateClass([
32713
- r5()
32714
- ], BeamSidebar.prototype, "_recentPhotons", 2);
32715
33118
  __decorateClass([
32716
33119
  r5()
32717
33120
  ], BeamSidebar.prototype, "_notificationWarmth", 2);
@@ -35056,7 +35459,7 @@ var InvokeForm = class extends i4 {
35056
35459
  }
35057
35460
  /** Cancel with dirty check. Called by parent chrome wrapper. */
35058
35461
  async handleCancel() {
35059
- if (this.isDirty && !await confirmDialog("You have unsaved changes. Discard them?", {
35462
+ if (this.isDirty && !await confirmElicit("You have unsaved changes. Discard them?", {
35060
35463
  confirm: "Discard",
35061
35464
  destructive: true
35062
35465
  })) {
@@ -46423,7 +46826,7 @@ var MarketplaceView = class extends i4 {
46423
46826
  this._items = items;
46424
46827
  }
46425
46828
  async _removeSource(name2) {
46426
- if (!await confirmDialog(`Remove marketplace "${name2}"? This will not uninstall any photons.`, {
46829
+ if (!await confirmElicit(`Remove marketplace "${name2}"? This will not uninstall any photons.`, {
46427
46830
  confirm: "Remove",
46428
46831
  destructive: true
46429
46832
  })) {
@@ -46490,7 +46893,7 @@ var MarketplaceView = class extends i4 {
46490
46893
  }
46491
46894
  }
46492
46895
  async _remove(item) {
46493
- if (!await confirmDialog(`Remove "${item.name}"? This will delete the photon files.`, {
46896
+ if (!await confirmElicit(`Remove "${item.name}"? This will delete the photon files.`, {
46494
46897
  confirm: "Remove",
46495
46898
  destructive: true
46496
46899
  }))
@@ -47947,7 +48350,8 @@ var CustomUiRenderer = class extends i4 {
47947
48350
  if (body) {
47948
48351
  const bodyOverflow = iframe.contentDocument?.defaultView ? getComputedStyle(iframe.contentDocument.body).overflow : "";
47949
48352
  const isFullHeightApp = bodyOverflow === "hidden";
47950
- if (!isFullHeightApp) {
48353
+ const hostHasExplicitHeight = this.style.height && this.style.height !== "auto";
48354
+ if (!isFullHeightApp && !hostHasExplicitHeight) {
47951
48355
  this._contentResizeObserver = new ResizeObserver(() => {
47952
48356
  const scrollH = iframe.contentDocument?.body.scrollHeight ?? 0;
47953
48357
  const containerH = this.offsetHeight || 500;
@@ -95191,6 +95595,7 @@ var PhotonStudio = class extends i4 {
95191
95595
  super(...arguments);
95192
95596
  this.photonName = "";
95193
95597
  this.theme = "dark";
95598
+ this.hideCloseButton = false;
95194
95599
  this._source = "";
95195
95600
  this._originalSource = "";
95196
95601
  this._dirty = false;
@@ -95682,7 +96087,7 @@ ${indent}* ` },
95682
96087
  return;
95683
96088
  }
95684
96089
  const currentName = seedPlan.symbolName.replace(/^\(alias\)\s*/, "").trim();
95685
- const nextName = window.prompt("Rename symbol to:", currentName);
96090
+ const nextName = await promptElicit("Rename symbol to:", currentName);
95686
96091
  if (!nextName || nextName === currentName) return;
95687
96092
  const renamePlan = await this._tsWorkerClient.rename(this._filePath, this._source, pos, nextName).catch((error2) => {
95688
96093
  showToast(error2 instanceof Error ? error2.message : String(error2), "error");
@@ -96098,7 +96503,7 @@ ${indent}* ` },
96098
96503
  }
96099
96504
  async _close() {
96100
96505
  if (this._dirty) {
96101
- if (!await confirmDialog("You have unsaved changes. Close anyway?", {
96506
+ if (!await confirmElicit("You have unsaved changes. Close anyway?", {
96102
96507
  confirm: "Close",
96103
96508
  destructive: true
96104
96509
  }))
@@ -96111,7 +96516,7 @@ ${indent}* ` },
96111
96516
  return b2`
96112
96517
  <div class="toolbar">
96113
96518
  <span class="toolbar-title">Studio</span>
96114
- <button class="close-btn" @click=${() => this._close()}>&times;</button>
96519
+ ${!this.hideCloseButton ? b2`<button class="close-btn" @click=${() => this._close()}>&times;</button>` : ""}
96115
96520
  </div>
96116
96521
  <div class="loading-state">Loading source...</div>
96117
96522
  `;
@@ -96119,8 +96524,8 @@ ${indent}* ` },
96119
96524
  if (this._error) {
96120
96525
  return b2`
96121
96526
  <div class="toolbar">
96122
- <span class="toolbar-title">Studio</span>
96123
- <button class="close-btn" @click=${() => this._close()}>&times;</button>
96527
+ <span class="toolbar-title">Studio Error</span>
96528
+ ${!this.hideCloseButton ? b2`<button class="close-btn" @click=${() => this._close()}>&times;</button>` : ""}
96124
96529
  </div>
96125
96530
  <div class="error-state">
96126
96531
  <span>${this._error}</span>
@@ -96195,9 +96600,9 @@ ${indent}* ` },
96195
96600
  ${this._saving ? "Saving..." : "Save"}
96196
96601
  </button>
96197
96602
 
96198
- <button class="close-btn" @click=${() => this._close()} title="Close Studio">
96199
- &times;
96200
- </button>
96603
+ ${!this.hideCloseButton ? b2`<button class="close-btn" @click=${() => this._close()} title="Close Studio">
96604
+ &times;
96605
+ </button>` : ""}
96201
96606
  </div>
96202
96607
 
96203
96608
  <div class="studio-body">
@@ -97241,6 +97646,9 @@ __decorateClass([
97241
97646
  __decorateClass([
97242
97647
  n4()
97243
97648
  ], PhotonStudio.prototype, "theme", 2);
97649
+ __decorateClass([
97650
+ n4({ type: Boolean })
97651
+ ], PhotonStudio.prototype, "hideCloseButton", 2);
97244
97652
  __decorateClass([
97245
97653
  r5()
97246
97654
  ], PhotonStudio.prototype, "_source", 2);
@@ -97783,7 +98191,11 @@ var ElicitationModal = class extends i4 {
97783
98191
  aria-label="${this.data?.message || "Input required"}"
97784
98192
  @click=${(e8) => e8.stopPropagation()}
97785
98193
  >
97786
- <h3>${this.data.message || "Input Required"}</h3>
98194
+ ${this.data.icon ? b2`<div class="modal-icon">${this.data.icon}</div>` : A}
98195
+ <h3 class="${this.data.description ? "has-description" : ""}">
98196
+ ${this.data.message || "Input Required"}
98197
+ </h3>
98198
+ ${this.data.description ? b2`<p class="modal-description">${this.data.description}</p>` : A}
97787
98199
  ${this._renderContent()}
97788
98200
  </div>
97789
98201
  `;
@@ -97823,8 +98235,12 @@ var ElicitationModal = class extends i4 {
97823
98235
  />
97824
98236
  </div>
97825
98237
  <div class="actions">
97826
- <button class="btn-secondary" @click=${() => this._cancel()}>Cancel</button>
97827
- <button class="btn-primary" @click=${() => this._submit()}>Submit</button>
98238
+ <button class="btn-secondary" @click=${() => this._cancel()}>
98239
+ ${this.data?.cancelLabel || "Cancel"}
98240
+ </button>
98241
+ <button class="btn-primary" @click=${() => this._submit()}>
98242
+ ${this.data?.submitLabel || "Submit"}
98243
+ </button>
97828
98244
  </div>
97829
98245
  `;
97830
98246
  }
@@ -98321,13 +98737,31 @@ ElicitationModal.styles = [
98321
98737
  animation-delay: 0.05s;
98322
98738
  }
98323
98739
 
98740
+ .modal-icon {
98741
+ font-size: 2.5rem;
98742
+ text-align: center;
98743
+ margin-bottom: var(--space-sm);
98744
+ line-height: 1;
98745
+ }
98746
+
98324
98747
  h3 {
98325
- margin: 0 0 var(--space-lg) 0;
98748
+ margin: 0 0 var(--space-sm) 0;
98326
98749
  font-size: var(--text-xl);
98327
98750
  font-weight: 600;
98328
98751
  color: var(--t-primary);
98329
98752
  }
98330
98753
 
98754
+ .modal-description {
98755
+ margin: 0 0 var(--space-lg) 0;
98756
+ font-size: var(--text-md);
98757
+ color: var(--t-muted);
98758
+ line-height: 1.5;
98759
+ }
98760
+
98761
+ h3:not(.has-description) {
98762
+ margin-bottom: var(--space-lg);
98763
+ }
98764
+
98331
98765
  .actions {
98332
98766
  display: flex;
98333
98767
  gap: var(--space-sm);
@@ -99939,9 +100373,7 @@ var ContextBar = class extends i4 {
99939
100373
  ${this.showConfigure && !p5.isExternalMCP ? b2`<button class="action-btn" @click=${() => this._emit("configure")}>
99940
100374
  Reconfigure
99941
100375
  </button>` : ""}
99942
- ${this.showCopyConfig ? b2`<button class="action-btn" @click=${() => this._emit("copy-config")}>
99943
- ${clipboard} Copy MCP Config
99944
- </button>` : ""}
100376
+ ${""}<!-- Copy MCP Config moved to overflow menu -->
99945
100377
  ${this.overflowItems.length > 0 ? b2`<overflow-menu
99946
100378
  .items=${this.overflowItems}
99947
100379
  @menu-select=${(e8) => this._emit("overflow", e8.detail)}