@portel/photon 1.19.0 → 1.20.0

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 (92) hide show
  1. package/dist/auto-ui/beam/routes/api-browse.d.ts.map +1 -1
  2. package/dist/auto-ui/beam/routes/api-browse.js +16 -4
  3. package/dist/auto-ui/beam/routes/api-browse.js.map +1 -1
  4. package/dist/auto-ui/beam/routes/api-config.js +4 -4
  5. package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
  6. package/dist/auto-ui/beam/routes/api-marketplace.d.ts.map +1 -1
  7. package/dist/auto-ui/beam/routes/api-marketplace.js +14 -1
  8. package/dist/auto-ui/beam/routes/api-marketplace.js.map +1 -1
  9. package/dist/auto-ui/beam.d.ts.map +1 -1
  10. package/dist/auto-ui/beam.js +183 -74
  11. package/dist/auto-ui/beam.js.map +1 -1
  12. package/dist/auto-ui/bridge/index.d.ts.map +1 -1
  13. package/dist/auto-ui/bridge/index.js +17 -0
  14. package/dist/auto-ui/bridge/index.js.map +1 -1
  15. package/dist/auto-ui/streamable-http-transport.d.ts +1 -0
  16. package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
  17. package/dist/auto-ui/streamable-http-transport.js +64 -16
  18. package/dist/auto-ui/streamable-http-transport.js.map +1 -1
  19. package/dist/auto-ui/types.d.ts +12 -0
  20. package/dist/auto-ui/types.d.ts.map +1 -1
  21. package/dist/auto-ui/types.js.map +1 -1
  22. package/dist/beam-form.bundle.js +44 -3
  23. package/dist/beam-form.bundle.js.map +2 -2
  24. package/dist/beam.bundle.js +1404 -482
  25. package/dist/beam.bundle.js.map +4 -4
  26. package/dist/capability-negotiator.d.ts +67 -0
  27. package/dist/capability-negotiator.d.ts.map +1 -0
  28. package/dist/capability-negotiator.js +104 -0
  29. package/dist/capability-negotiator.js.map +1 -0
  30. package/dist/channel-manager.d.ts +122 -0
  31. package/dist/channel-manager.d.ts.map +1 -0
  32. package/dist/channel-manager.js +266 -0
  33. package/dist/channel-manager.js.map +1 -0
  34. package/dist/cli/commands/package.d.ts.map +1 -1
  35. package/dist/cli/commands/package.js +25 -7
  36. package/dist/cli/commands/package.js.map +1 -1
  37. package/dist/daemon/client.d.ts.map +1 -1
  38. package/dist/daemon/client.js +12 -0
  39. package/dist/daemon/client.js.map +1 -1
  40. package/dist/daemon/server.js +30 -49
  41. package/dist/daemon/server.js.map +1 -1
  42. package/dist/daemon/worker-manager.d.ts.map +1 -1
  43. package/dist/daemon/worker-manager.js +21 -7
  44. package/dist/daemon/worker-manager.js.map +1 -1
  45. package/dist/loader.d.ts +4 -1
  46. package/dist/loader.d.ts.map +1 -1
  47. package/dist/loader.js +73 -11
  48. package/dist/loader.js.map +1 -1
  49. package/dist/marketplace-manager.d.ts +6 -0
  50. package/dist/marketplace-manager.d.ts.map +1 -1
  51. package/dist/marketplace-manager.js +161 -58
  52. package/dist/marketplace-manager.js.map +1 -1
  53. package/dist/namespace-migration.d.ts +1 -0
  54. package/dist/namespace-migration.d.ts.map +1 -1
  55. package/dist/namespace-migration.js +86 -0
  56. package/dist/namespace-migration.js.map +1 -1
  57. package/dist/resource-server.d.ts +105 -0
  58. package/dist/resource-server.d.ts.map +1 -0
  59. package/dist/resource-server.js +723 -0
  60. package/dist/resource-server.js.map +1 -0
  61. package/dist/serv/auth/jwt.d.ts +2 -0
  62. package/dist/serv/auth/jwt.d.ts.map +1 -1
  63. package/dist/serv/auth/jwt.js +11 -5
  64. package/dist/serv/auth/jwt.js.map +1 -1
  65. package/dist/serv/vault/token-vault.d.ts +2 -0
  66. package/dist/serv/vault/token-vault.d.ts.map +1 -1
  67. package/dist/serv/vault/token-vault.js +6 -0
  68. package/dist/serv/vault/token-vault.js.map +1 -1
  69. package/dist/server.d.ts +20 -149
  70. package/dist/server.d.ts.map +1 -1
  71. package/dist/server.js +232 -1217
  72. package/dist/server.js.map +1 -1
  73. package/dist/shared/audit.d.ts.map +1 -1
  74. package/dist/shared/audit.js +7 -0
  75. package/dist/shared/audit.js.map +1 -1
  76. package/dist/shared/security.d.ts +10 -0
  77. package/dist/shared/security.d.ts.map +1 -1
  78. package/dist/shared/security.js +27 -0
  79. package/dist/shared/security.js.map +1 -1
  80. package/dist/task-executor.d.ts +69 -0
  81. package/dist/task-executor.d.ts.map +1 -0
  82. package/dist/task-executor.js +182 -0
  83. package/dist/task-executor.js.map +1 -0
  84. package/dist/types/photon-instance.d.ts +50 -0
  85. package/dist/types/photon-instance.d.ts.map +1 -0
  86. package/dist/types/photon-instance.js +9 -0
  87. package/dist/types/photon-instance.js.map +1 -0
  88. package/dist/types/server-types.d.ts +61 -0
  89. package/dist/types/server-types.d.ts.map +1 -0
  90. package/dist/types/server-types.js +8 -0
  91. package/dist/types/server-types.js.map +1 -0
  92. package/package.json +2 -2
@@ -21740,8 +21740,13 @@ var MCPClientService = class {
21740
21740
  id: tool["x-photon-id"] || serverName,
21741
21741
  // Use hash ID, fallback to name
21742
21742
  name: serverName,
21743
+ shortName: tool["x-photon-short-name"],
21744
+ namespace: tool["x-photon-namespace"],
21745
+ qualifiedName: tool["x-photon-qualified-name"],
21743
21746
  path: tool["x-photon-path"],
21744
21747
  // File path for View Source
21748
+ editable: tool["x-photon-editable"] ?? false,
21749
+ // User-owned (at baseDir root)
21745
21750
  description: tool["x-photon-description"],
21746
21751
  icon: tool["x-photon-icon"],
21747
21752
  internal: tool["x-photon-internal"],
@@ -22435,6 +22440,62 @@ var ViewportManager = class {
22435
22440
  }
22436
22441
  };
22437
22442
 
22443
+ // src/auto-ui/frontend/utils/beam-route.ts
22444
+ function decodeBeamPathSegments(pathname) {
22445
+ return pathname.split("/").filter(Boolean).map((segment) => {
22446
+ try {
22447
+ return decodeURIComponent(segment);
22448
+ } catch {
22449
+ return segment;
22450
+ }
22451
+ });
22452
+ }
22453
+ function matchesNamespacedPhoton(photon, namespace, shortName) {
22454
+ return photon.namespace === namespace && (photon.shortName || photon.name) === shortName;
22455
+ }
22456
+ function parseBeamRoutePath(pathname, photons, externalMCPs = []) {
22457
+ const segments = decodeBeamPathSegments(pathname);
22458
+ if (segments.length === 0) {
22459
+ return { photonName: null, methodNames: [] };
22460
+ }
22461
+ if (segments.length === 1) {
22462
+ return { photonName: segments[0], methodNames: [] };
22463
+ }
22464
+ if (segments.length === 2) {
22465
+ const [first, second] = segments;
22466
+ const namespacedPhoton2 = photons.find(
22467
+ (photon) => matchesNamespacedPhoton(photon, first, second)
22468
+ );
22469
+ if (namespacedPhoton2) {
22470
+ return { photonName: namespacedPhoton2.name, methodNames: [] };
22471
+ }
22472
+ return { photonName: first, methodNames: second.split("+").filter(Boolean) };
22473
+ }
22474
+ const namespace = segments[segments.length - 3];
22475
+ const shortName = segments[segments.length - 2];
22476
+ const methodSegment = segments[segments.length - 1];
22477
+ const namespacedPhoton = photons.find((photon) => matchesNamespacedPhoton(photon, namespace, shortName)) || externalMCPs.find((photon) => matchesNamespacedPhoton(photon, namespace, shortName));
22478
+ if (namespacedPhoton) {
22479
+ return {
22480
+ photonName: namespacedPhoton.name,
22481
+ methodNames: methodSegment.split("+").filter(Boolean)
22482
+ };
22483
+ }
22484
+ const photonName = segments[segments.length - 2];
22485
+ return { photonName, methodNames: methodSegment.split("+").filter(Boolean) };
22486
+ }
22487
+ function buildBeamRoutePath(photon, methodName, splitPanelMethodNames = []) {
22488
+ if (!photon) return "/";
22489
+ const baseSegments = photon.namespace && photon.shortName ? [photon.namespace, photon.shortName] : [photon.name];
22490
+ if (!methodName) {
22491
+ return "/" + baseSegments.map((segment) => encodeURIComponent(segment)).join("/");
22492
+ }
22493
+ const methodSegments = [methodName, ...splitPanelMethodNames].map(
22494
+ (name2) => encodeURIComponent(name2)
22495
+ );
22496
+ return "/" + baseSegments.map((segment) => encodeURIComponent(segment)).join("/") + "/" + methodSegments.join("+");
22497
+ }
22498
+
22438
22499
  // src/auto-ui/frontend/components/beam-app.ts
22439
22500
  var THEME_STORAGE_KEY = "beam-theme";
22440
22501
  var PROTOCOL_STORAGE_KEY = "beam-protocol";
@@ -22449,6 +22510,10 @@ var BeamApp = class extends i4 {
22449
22510
  this._reconnectAttempt = 0;
22450
22511
  this._connectRetries = 0;
22451
22512
  this._sidebarVisible = false;
22513
+ this._sidebarWidth = parseInt(
22514
+ localStorage.getItem("beam-sidebar-width") || "300",
22515
+ 10
22516
+ );
22452
22517
  this._focusMode = false;
22453
22518
  this._viewMode = "full";
22454
22519
  this._photons = [];
@@ -22503,7 +22568,11 @@ var BeamApp = class extends i4 {
22503
22568
  this._splitPanels = [];
22504
22569
  this._methodPickerOpen = false;
22505
22570
  this._methodPickerPanelId = null;
22571
+ this._splitPrimaryWidth = null;
22572
+ this._mainTab = "methods";
22506
22573
  this._nextPanelId = 0;
22574
+ // Maps progressToken → panelId so progress events route to the correct split pane
22575
+ this._panelProgressTokens = /* @__PURE__ */ new Map();
22507
22576
  // Collection auto-subscription for ReactiveArray/Map/Set events
22508
22577
  this._collectionUnsubscribes = [];
22509
22578
  this._currentCollectionName = null;
@@ -22538,9 +22607,13 @@ var BeamApp = class extends i4 {
22538
22607
  this._initialConnectDone = false;
22539
22608
  this._handleRouteChange = () => {
22540
22609
  void (async () => {
22541
- const fullPath = window.location.pathname.slice(1);
22542
22610
  const queryPart = window.location.search.slice(1);
22543
- const [photonName, methodName] = fullPath.split("/");
22611
+ const { photonName, methodNames } = parseBeamRoutePath(
22612
+ window.location.pathname,
22613
+ this._photons,
22614
+ this._externalMCPs
22615
+ );
22616
+ const methodName = methodNames[0];
22544
22617
  this._sharedFormParams = null;
22545
22618
  let sharedParams = {};
22546
22619
  if (queryPart) {
@@ -22603,10 +22676,11 @@ var BeamApp = class extends i4 {
22603
22676
  if (photon.isExternalMCP && photon.hasMcpApp) {
22604
22677
  this._selectedMethod = null;
22605
22678
  this._view = "mcp-app";
22679
+ this._mainTab = "app";
22606
22680
  return;
22607
22681
  }
22608
22682
  if (methodName && photon.methods) {
22609
- const [firstMethodName, secondMethodName] = methodName.split("+");
22683
+ const [firstMethodName, secondMethodName] = methodNames;
22610
22684
  const method = photon.methods.find((m3) => m3.name === firstMethodName);
22611
22685
  if (method) {
22612
22686
  if (Object.keys(sharedParams).length > 0) {
@@ -22617,11 +22691,13 @@ var BeamApp = class extends i4 {
22617
22691
  }
22618
22692
  this._selectedMethod = method;
22619
22693
  this._view = "form";
22694
+ if (photon.isApp && photon.appEntry?.name === method.name) {
22695
+ this._mainTab = "app";
22696
+ } else if (!photon.isApp) {
22697
+ this._mainTab = "methods";
22698
+ }
22620
22699
  this._maybeAutoInvoke(method);
22621
22700
  if (secondMethodName) {
22622
- const urlPath = location.pathname;
22623
- const methodPart = urlPath.split("/").pop() || "";
22624
- const methodNames = methodPart.split("+");
22625
22701
  for (let i7 = 1; i7 < methodNames.length; i7++) {
22626
22702
  const name2 = methodNames[i7];
22627
22703
  if (name2 === "source") {
@@ -22644,10 +22720,12 @@ var BeamApp = class extends i4 {
22644
22720
  }
22645
22721
  this._selectedMethod = photon.appEntry;
22646
22722
  this._view = "form";
22723
+ this._mainTab = "app";
22647
22724
  this._maybeAutoInvoke(photon.appEntry);
22648
22725
  } else {
22649
22726
  this._selectedMethod = null;
22650
22727
  this._view = "list";
22728
+ this._mainTab = "methods";
22651
22729
  }
22652
22730
  }
22653
22731
  }
@@ -22847,7 +22925,7 @@ var BeamApp = class extends i4 {
22847
22925
  try {
22848
22926
  const res = await fetch("/api/marketplace/add", {
22849
22927
  method: "POST",
22850
- headers: { "Content-Type": "application/json" },
22928
+ headers: { "Content-Type": "application/json", "X-Photon-Request": "1" },
22851
22929
  body: JSON.stringify({ name: name2 }),
22852
22930
  signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
22853
22931
  });
@@ -22876,15 +22954,19 @@ var BeamApp = class extends i4 {
22876
22954
  this._showForkDialog = false;
22877
22955
  this._forkPhotonName = "";
22878
22956
  this._forkOriginRepo = "";
22957
+ this._forkRequireNewName = false;
22958
+ this._forkSuggestedName = "";
22879
22959
  this._forkTargets = [];
22880
22960
  this._handleFork = async () => {
22881
22961
  if (!this._selectedPhoton) return;
22882
- this._forkPhotonName = this._selectedPhoton.name;
22962
+ this._forkPhotonName = this._selectedPhoton.qualifiedName || this._selectedPhoton.name;
22883
22963
  this._forkOriginRepo = this._selectedPhoton.installSource?.marketplace || "";
22964
+ this._forkRequireNewName = !this._selectedPhoton.installSource;
22965
+ this._forkSuggestedName = `${this._selectedPhoton.shortName || this._selectedPhoton.name}-copy`;
22884
22966
  await this._openForkDialog();
22885
22967
  };
22886
22968
  this._handleForkConfirm = async (e8) => {
22887
- const { target: target2 } = e8.detail;
22969
+ const { target: target2, newName } = e8.detail;
22888
22970
  const name2 = this._forkPhotonName;
22889
22971
  if (!name2) return;
22890
22972
  this._showForkDialog = false;
@@ -22892,8 +22974,8 @@ var BeamApp = class extends i4 {
22892
22974
  try {
22893
22975
  const res = await fetch("/api/marketplace/fork", {
22894
22976
  method: "POST",
22895
- headers: { "Content-Type": "application/json" },
22896
- body: JSON.stringify({ name: name2, target: target2 }),
22977
+ headers: { "Content-Type": "application/json", "X-Photon-Request": "1" },
22978
+ body: JSON.stringify({ name: name2, target: target2, newName }),
22897
22979
  signal: AbortSignal.timeout(3e4)
22898
22980
  });
22899
22981
  const result = await res.json();
@@ -22920,6 +23002,8 @@ var BeamApp = class extends i4 {
22920
23002
  const { name: name2 } = e8.detail;
22921
23003
  this._forkPhotonName = name2;
22922
23004
  this._forkOriginRepo = "";
23005
+ this._forkRequireNewName = false;
23006
+ this._forkSuggestedName = `${name2}-copy`;
22923
23007
  await this._openForkDialog();
22924
23008
  };
22925
23009
  this._handleContribute = async () => {
@@ -22929,7 +23013,7 @@ var BeamApp = class extends i4 {
22929
23013
  try {
22930
23014
  const res = await fetch("/api/marketplace/contribute", {
22931
23015
  method: "POST",
22932
- headers: { "Content-Type": "application/json" },
23016
+ headers: { "Content-Type": "application/json", "X-Photon-Request": "1" },
22933
23017
  body: JSON.stringify({ name: name2 }),
22934
23018
  signal: AbortSignal.timeout(6e4)
22935
23019
  });
@@ -23023,7 +23107,8 @@ var BeamApp = class extends i4 {
23023
23107
  const data = mcpClient.parseToolResult(result);
23024
23108
  if (data && data.code) {
23025
23109
  this._sourceData = data;
23026
- this._showSourceModal = true;
23110
+ this._mainTab = "source";
23111
+ this._view = "source";
23027
23112
  } else {
23028
23113
  showToast("No source code returned", "error");
23029
23114
  }
@@ -23035,14 +23120,17 @@ var BeamApp = class extends i4 {
23035
23120
  };
23036
23121
  /** Navigate to inline source view (Phase 2) */
23037
23122
  this._handleViewSourceInline = async () => {
23038
- if (this._view === "source") {
23039
- this._view = "studio";
23123
+ if (this._view === "source" || this._view === "studio") {
23040
23124
  return;
23041
23125
  }
23042
- await this._handleViewSource();
23043
- if (this._sourceData) {
23044
- this._showSourceModal = false;
23045
- this._view = "source";
23126
+ const isEditable = this._selectedPhoton?.editable && !this._selectedPhoton?.isExternalMCP;
23127
+ if (isEditable) {
23128
+ this._view = "studio";
23129
+ } else {
23130
+ await this._handleViewSource();
23131
+ if (this._sourceData) {
23132
+ this._view = "source";
23133
+ }
23046
23134
  }
23047
23135
  };
23048
23136
  /** Open settings for the current photon (Phase 3) */
@@ -23112,12 +23200,15 @@ var BeamApp = class extends i4 {
23112
23200
  const newName = detail.cloneName;
23113
23201
  if (!newName) return;
23114
23202
  try {
23115
- const res = await fetch(`/api/instances/${photonName}/${detail.instance}/clone`, {
23116
- method: "POST",
23117
- headers: { "Content-Type": "application/json" },
23118
- body: JSON.stringify({ newName }),
23119
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
23120
- });
23203
+ const res = await fetch(
23204
+ `/api/instances/${encodeURIComponent(photonName)}/${encodeURIComponent(detail.instance)}/clone`,
23205
+ {
23206
+ method: "POST",
23207
+ headers: { "Content-Type": "application/json" },
23208
+ body: JSON.stringify({ newName }),
23209
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
23210
+ }
23211
+ );
23121
23212
  if (res.ok) {
23122
23213
  await this._fetchInstances(photonName);
23123
23214
  showToast(`Cloned as: ${newName}`, "success");
@@ -23134,12 +23225,15 @@ var BeamApp = class extends i4 {
23134
23225
  const newName = detail.newName;
23135
23226
  if (!newName) return;
23136
23227
  try {
23137
- const res = await fetch(`/api/instances/${photonName}/${detail.instance}/rename`, {
23138
- method: "POST",
23139
- headers: { "Content-Type": "application/json" },
23140
- body: JSON.stringify({ newName }),
23141
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
23142
- });
23228
+ const res = await fetch(
23229
+ `/api/instances/${encodeURIComponent(photonName)}/${encodeURIComponent(detail.instance)}/rename`,
23230
+ {
23231
+ method: "POST",
23232
+ headers: { "Content-Type": "application/json" },
23233
+ body: JSON.stringify({ newName }),
23234
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
23235
+ }
23236
+ );
23143
23237
  if (res.ok) {
23144
23238
  await mcpClient.callTool(`${photonName}/_use`, { name: newName });
23145
23239
  this._setCurrentInstance(photonName, newName);
@@ -23161,10 +23255,13 @@ var BeamApp = class extends i4 {
23161
23255
  return;
23162
23256
  }
23163
23257
  try {
23164
- const res = await fetch(`/api/instances/${photonName}/${instanceToDelete}`, {
23165
- method: "DELETE",
23166
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
23167
- });
23258
+ const res = await fetch(
23259
+ `/api/instances/${encodeURIComponent(photonName)}/${encodeURIComponent(instanceToDelete)}`,
23260
+ {
23261
+ method: "DELETE",
23262
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
23263
+ }
23264
+ );
23168
23265
  if (res.ok) {
23169
23266
  await mcpClient.callTool(`${photonName}/_use`, { name: "default" });
23170
23267
  this._setCurrentInstance(photonName, "default");
@@ -23479,16 +23576,9 @@ var BeamApp = class extends i4 {
23479
23576
  this._showHelp = false;
23480
23577
  return;
23481
23578
  }
23482
- if (this._showPhotonHelp) {
23483
- this._showPhotonHelp = false;
23484
- return;
23485
- }
23486
- if (this._view === "source") {
23487
- this._view = "list";
23488
- return;
23489
- }
23490
- if (this._showSourceModal) {
23491
- this._closeSourceModal();
23579
+ if (this._mainTab === "help" || this._mainTab === "source") {
23580
+ this._mainTab = "methods";
23581
+ if (this._view === "source") this._view = "list";
23492
23582
  return;
23493
23583
  }
23494
23584
  if (this._view === "form" && this._selectedMethod) {
@@ -23603,6 +23693,26 @@ var BeamApp = class extends i4 {
23603
23693
  this._photonHelpLoading = false;
23604
23694
  }
23605
23695
  };
23696
+ /** Load help content for inline help tab view */
23697
+ this._loadPhotonHelp = async () => {
23698
+ if (!this._selectedPhoton) return;
23699
+ this._photonHelpMarkdown = "";
23700
+ this._photonHelpLoading = true;
23701
+ const markdown = await mcpClient.getPhotonHelp(this._selectedPhoton.name);
23702
+ if (markdown) {
23703
+ this._photonHelpMarkdown = markdown;
23704
+ } else {
23705
+ this._photonHelpMarkdown = this._generatePhotonHelpMarkdown();
23706
+ }
23707
+ this._photonHelpLoading = false;
23708
+ if (this._view === "source" || this._view === "studio") {
23709
+ if (this._selectedMethod) {
23710
+ this._view = "form";
23711
+ } else {
23712
+ this._view = "list";
23713
+ }
23714
+ }
23715
+ };
23606
23716
  this._toggleFocusMode = () => {
23607
23717
  this._focusMode = !this._focusMode;
23608
23718
  if (this._focusMode) {
@@ -23706,7 +23816,8 @@ var BeamApp = class extends i4 {
23706
23816
  void this._handleRemove();
23707
23817
  break;
23708
23818
  case "help":
23709
- void this._showPhotonHelpModal();
23819
+ this._mainTab = "help";
23820
+ void this._loadPhotonHelp();
23710
23821
  break;
23711
23822
  case "fullscreen":
23712
23823
  this._handleFullscreen();
@@ -24240,8 +24351,12 @@ var BeamApp = class extends i4 {
24240
24351
  }
24241
24352
  }
24242
24353
  if (!this._selectedPhoton && window.location.pathname !== "/") {
24243
- const pathPhotonName = window.location.pathname.slice(1).split("/")[0];
24244
- const routePhoton = pathPhotonName ? this._photons.find((p5) => p5.name === pathPhotonName) : null;
24354
+ const { photonName: pathPhotonName } = parseBeamRoutePath(
24355
+ window.location.pathname,
24356
+ this._photons,
24357
+ this._externalMCPs
24358
+ );
24359
+ const routePhoton = pathPhotonName ? this._photons.find((p5) => p5.name === pathPhotonName) || this._externalMCPs.find((p5) => p5.name === pathPhotonName) : null;
24245
24360
  if (routePhoton) {
24246
24361
  void this._handleRouteChange();
24247
24362
  } else {
@@ -24263,18 +24378,15 @@ var BeamApp = class extends i4 {
24263
24378
  });
24264
24379
  mcpClient.on("progress", (data) => {
24265
24380
  this._log("info", data.message || "Processing...");
24266
- if (typeof data.progress === "number") {
24267
- if (data.progress > 0) {
24268
- this._progress = {
24269
- value: data.total ? data.progress / data.total : data.progress,
24270
- message: data.message || "Processing..."
24271
- };
24272
- } else {
24273
- this._progress = {
24274
- value: -1,
24275
- message: data.message || "Processing..."
24276
- };
24277
- }
24381
+ const panelId = data.progressToken != null ? this._panelProgressTokens.get(data.progressToken) : void 0;
24382
+ const progressValue = typeof data.progress === "number" ? data.progress > 0 ? {
24383
+ value: data.total ? data.progress / data.total : data.progress,
24384
+ message: data.message || "Processing..."
24385
+ } : { value: -1, message: data.message || "Processing..." } : null;
24386
+ if (panelId && progressValue) {
24387
+ this._updatePanel(panelId, { progress: progressValue });
24388
+ } else if (progressValue) {
24389
+ this._progress = progressValue;
24278
24390
  }
24279
24391
  });
24280
24392
  mcpClient.on("toast", (data) => {
@@ -24576,17 +24688,16 @@ var BeamApp = class extends i4 {
24576
24688
  } else if (!this._selectedPhoton) {
24577
24689
  path = "/";
24578
24690
  } else {
24579
- path = "/" + this._selectedPhoton.name;
24580
- if (this._selectedMethod) {
24581
- path += `/${this._selectedMethod.name}`;
24582
- for (const panel of this._splitPanels) {
24583
- if (panel.type === "method" && panel.method) {
24584
- path += `+${panel.method.name}`;
24585
- } else if (panel.type === "source") {
24586
- path += `+source`;
24587
- }
24588
- }
24589
- }
24691
+ const splitPanelMethodNames = this._selectedMethod ? this._splitPanels.map((panel) => {
24692
+ if (panel.type === "method" && panel.method) return panel.method.name;
24693
+ if (panel.type === "source") return "source";
24694
+ return null;
24695
+ }).filter((name2) => !!name2) : [];
24696
+ path = buildBeamRoutePath(
24697
+ this._selectedPhoton,
24698
+ this._selectedMethod?.name,
24699
+ splitPanelMethodNames
24700
+ );
24590
24701
  }
24591
24702
  if (replace2) {
24592
24703
  history.replaceState(null, "", path);
@@ -24975,7 +25086,7 @@ var BeamApp = class extends i4 {
24975
25086
 
24976
25087
  <nav
24977
25088
  class="sidebar-area glass-panel ${this._sidebarVisible ? "visible" : ""}"
24978
- style="margin: var(--space-sm); border-radius: var(--radius-md);"
25089
+ style="margin: var(--space-sm); border-radius: var(--radius-md); --sidebar-width: ${this._sidebarWidth}px;"
24979
25090
  aria-label="Photon navigation"
24980
25091
  >
24981
25092
  <beam-sidebar
@@ -24986,6 +25097,57 @@ var BeamApp = class extends i4 {
24986
25097
  .connected=${this._connected}
24987
25098
  .reconnecting=${this._reconnecting}
24988
25099
  .updatesAvailable=${this._updatesAvailable.length}
25100
+ .mainTab=${this._mainTab}
25101
+ .isApp=${!!(this._selectedPhoton?.isApp || this._selectedPhoton?.isExternalMCP && this._selectedPhoton?.hasMcpApp)}
25102
+ .hasSettings=${!!(this._selectedPhoton?.hasSettings && !this._selectedPhoton?.isExternalMCP)}
25103
+ .isExternalMCP=${!!this._selectedPhoton?.isExternalMCP}
25104
+ .hasPath=${!!this._selectedPhoton?.path}
25105
+ @tab-change=${(e8) => {
25106
+ const tab = e8.detail.tab;
25107
+ this._mainTab = tab;
25108
+ if (tab === "methods") {
25109
+ this._closeSecondPanel();
25110
+ this._selectedMethod = null;
25111
+ this._view = "list";
25112
+ this._updateRoute();
25113
+ return;
25114
+ }
25115
+ if (tab === "source") {
25116
+ void this._handleViewSourceInline();
25117
+ return;
25118
+ }
25119
+ if (tab === "help") {
25120
+ void this._loadPhotonHelp();
25121
+ return;
25122
+ }
25123
+ if (this._view === "source" || this._view === "studio") {
25124
+ if (this._selectedMethod) {
25125
+ this._view = "form";
25126
+ } else {
25127
+ this._view = "list";
25128
+ }
25129
+ }
25130
+ if (tab === "settings" && this._selectedPhoton) {
25131
+ const settingsMethod = this._selectedPhoton.methods?.find(
25132
+ (m3) => m3.name === "settings"
25133
+ );
25134
+ if (settingsMethod) {
25135
+ this._selectedMethod = settingsMethod;
25136
+ this._view = "form";
25137
+ this._maybeAutoInvoke(settingsMethod);
25138
+ }
25139
+ return;
25140
+ }
25141
+ if (tab === "app" && this._selectedPhoton?.isExternalMCP && this._selectedPhoton?.hasMcpApp) {
25142
+ this._view = "mcp-app";
25143
+ }
25144
+ if (tab === "app" && this._selectedPhoton?.isApp && this._selectedPhoton?.appEntry) {
25145
+ this._selectedMethod = this._selectedPhoton.appEntry;
25146
+ this._view = "form";
25147
+ this._maybeAutoInvoke(this._selectedPhoton.appEntry);
25148
+ }
25149
+ }}
25150
+ @toggle-focus=${() => this._toggleFocusMode()}
24989
25151
  @home=${this._goHome}
24990
25152
  @select=${(e8) => this._handlePhotonSelectMobile(e8)}
24991
25153
  @marketplace=${() => this._handleMarketplaceMobile()}
@@ -25001,7 +25163,7 @@ var BeamApp = class extends i4 {
25001
25163
  }}
25002
25164
  @open-studio=${(e8) => {
25003
25165
  const photon = this._photons.find((p5) => p5.name === e8.detail.photonName);
25004
- if (photon) {
25166
+ if (photon?.editable && !photon?.isExternalMCP) {
25005
25167
  this._selectedPhoton = photon;
25006
25168
  this._view = "studio";
25007
25169
  }
@@ -25015,61 +25177,20 @@ var BeamApp = class extends i4 {
25015
25177
  }
25016
25178
  }}
25017
25179
  ></beam-sidebar>
25180
+ <div
25181
+ class="sidebar-resize-handle"
25182
+ @pointerdown=${(e8) => this._handleSidebarResizeStart(e8)}
25183
+ ></div>
25018
25184
  </nav>
25019
25185
 
25020
- <main
25021
- class="main-area"
25022
- id="main-content"
25023
- tabindex="-1"
25024
- aria-label="Main content"
25025
- style="${this._splitViewEnabled ? "overflow: hidden !important;" : ""}"
25026
- >
25027
- ${this._focusMode && this._selectedPhoton ? b2`<div class="focus-toolbar">
25028
- ${this._selectedMethod && !this._selectedPhoton.isApp ? b2`<button
25029
- class="focus-toolbar-back"
25030
- @click=${() => this._handleBackFromMethod()}
25031
- @mouseenter=${(e8) => {
25032
- e8.target.style.color = "var(--t-primary)";
25033
- e8.target.style.borderColor = "var(--accent-primary)";
25034
- }}
25035
- @mouseleave=${(e8) => {
25036
- e8.target.style.color = "var(--t-muted)";
25037
- e8.target.style.borderColor = "var(--border-glass)";
25038
- }}
25039
- title="Back to ${this._selectedPhoton.name}"
25040
- >
25041
- <svg
25042
- width="16"
25043
- height="16"
25044
- viewBox="0 0 24 24"
25045
- fill="none"
25046
- stroke="currentColor"
25047
- stroke-width="2"
25048
- stroke-linecap="round"
25049
- stroke-linejoin="round"
25050
- >
25051
- <path d="m15 18-6-6 6-6" />
25052
- </svg>
25053
- </button>` : ""}
25054
- <button
25055
- @click=${this._toggleFocusMode}
25056
- @mouseenter=${(e8) => {
25057
- e8.target.style.color = "var(--t-primary)";
25058
- e8.target.style.borderColor = "var(--accent-primary)";
25059
- }}
25060
- @mouseleave=${(e8) => {
25061
- e8.target.style.color = "var(--t-muted)";
25062
- e8.target.style.borderColor = "var(--border-glass)";
25063
- }}
25064
- title="Exit focus mode"
25065
- >
25066
- ${collapse}
25067
- </button>
25068
- </div>` : ""}
25069
- ${this._selectedPhoton ? b2`<div class="main-toolbar">
25070
- <div>
25186
+ <main class="main-area" id="main-content" tabindex="-1" aria-label="Main content">
25187
+ <div
25188
+ class="main-content-scroll"
25189
+ style="${this._splitViewEnabled ? "overflow: hidden !important; padding: 0;" : this._mainTab === "app" && (this._selectedPhoton?.isApp || this._selectedPhoton?.isExternalMCP && this._selectedPhoton?.hasMcpApp) ? "overflow: hidden; padding: 0;" : this._mainTab === "source" ? "padding: 0; overflow: hidden;" : this._view === "studio" ? "padding: 0; overflow: hidden;" : ""}"
25190
+ >
25191
+ ${this._focusMode && this._selectedPhoton ? b2`<div class="focus-toolbar">
25071
25192
  ${this._selectedMethod && !this._selectedPhoton.isApp ? b2`<button
25072
- class="beam-back-btn"
25193
+ class="focus-toolbar-back"
25073
25194
  @click=${() => this._handleBackFromMethod()}
25074
25195
  @mouseenter=${(e8) => {
25075
25196
  e8.target.style.color = "var(--t-primary)";
@@ -25094,31 +25215,7 @@ var BeamApp = class extends i4 {
25094
25215
  <path d="m15 18-6-6 6-6" />
25095
25216
  </svg>
25096
25217
  </button>` : ""}
25097
- </div>
25098
- <div style="display: flex; gap: 4px; align-items: center;">
25099
- ${this._selectedPhoton.isApp ? b2`<div style="position: relative;">
25100
- <button
25101
- class="beam-fullscreen-btn"
25102
- @click=${() => {
25103
- this._methodPickerOpen = !this._methodPickerOpen;
25104
- this._methodPickerPanelId = null;
25105
- }}
25106
- @mouseenter=${(e8) => {
25107
- e8.target.style.color = "var(--accent-secondary)";
25108
- e8.target.style.borderColor = "var(--accent-secondary)";
25109
- }}
25110
- @mouseleave=${(e8) => {
25111
- e8.target.style.color = "var(--t-muted)";
25112
- e8.target.style.borderColor = "var(--border-glass)";
25113
- }}
25114
- title="Add panel"
25115
- >
25116
- +
25117
- </button>
25118
- ${this._methodPickerOpen && this._methodPickerPanelId === null ? this._renderMethodPickerPopover() : ""}
25119
- </div>` : ""}
25120
25218
  <button
25121
- class="beam-fullscreen-btn"
25122
25219
  @click=${this._toggleFocusMode}
25123
25220
  @mouseenter=${(e8) => {
25124
25221
  e8.target.style.color = "var(--t-primary)";
@@ -25128,18 +25225,21 @@ var BeamApp = class extends i4 {
25128
25225
  e8.target.style.color = "var(--t-muted)";
25129
25226
  e8.target.style.borderColor = "var(--border-glass)";
25130
25227
  }}
25131
- title=${this._focusMode ? "Exit focus mode" : "Focus mode"}
25228
+ title="Exit focus mode"
25132
25229
  >
25133
- ${this._focusMode ? collapse : expand}
25230
+ ${collapse}
25134
25231
  </button>
25135
- </div>
25136
- </div>` : ""}
25137
- ${this._renderContent()}
25138
- <activity-log
25139
- .items=${this._activityLog}
25140
- .filter=${this._selectedPhoton?.name}
25141
- @clear=${() => this._activityLog = []}
25142
- ></activity-log>
25232
+ </div>` : ""}
25233
+ ${this._selectedPhoton && !this._selectedMethod && this._mainTab === "methods" ? b2`<div class="main-toolbar">
25234
+ <div style="flex: 1; min-width: 0;">${this._renderPhotonToolbar()}</div>
25235
+ </div>` : ""}
25236
+ ${this._mainTab === "log" ? b2`<activity-log
25237
+ .items=${this._activityLog}
25238
+ .filter=${this._selectedPhoton?.name}
25239
+ .fullscreen=${true}
25240
+ @clear=${() => this._activityLog = []}
25241
+ ></activity-log>` : this._mainTab === "help" && this._selectedPhoton ? this._renderPhotonHelpView() : this._mainTab === "settings" && this._selectedPhoton ? this._renderSettingsView() : this._mainTab === "methods" && !this._selectedMethod && (this._selectedPhoton?.isApp || this._selectedPhoton?.isExternalMCP && this._selectedPhoton?.hasMcpApp) ? this._renderMethodsBentoOnly() : this._renderContent()}
25242
+ </div>
25143
25243
  </main>
25144
25244
 
25145
25245
  <toast-manager></toast-manager>
@@ -25160,13 +25260,13 @@ var BeamApp = class extends i4 {
25160
25260
  </div>
25161
25261
  ` : ""}
25162
25262
  ${this._showHelp ? this._renderHelpModal() : ""}
25163
- ${this._showPhotonHelp ? this._renderPhotonHelpModal() : ""}
25164
- ${this._showSourceModal ? this._renderSourceModal() : ""}
25165
25263
  ${this._selectedPrompt?.content ? this._renderPromptModal() : ""}
25166
25264
  ${this._selectedResource?.content ? this._renderResourceModal() : ""}
25167
25265
  ${this._showForkDialog ? b2`<fork-dialog
25168
25266
  .photonName=${this._forkPhotonName}
25169
25267
  .originRepo=${this._forkOriginRepo}
25268
+ .requireNewName=${this._forkRequireNewName}
25269
+ .suggestedName=${this._forkSuggestedName}
25170
25270
  .targets=${this._forkTargets}
25171
25271
  @fork-confirm=${this._handleForkConfirm}
25172
25272
  @fork-cancel=${() => {
@@ -25183,6 +25283,43 @@ var BeamApp = class extends i4 {
25183
25283
  ></elicitation-modal>
25184
25284
  `;
25185
25285
  }
25286
+ _renderMethodsBentoOnly() {
25287
+ if (!this._selectedPhoton) return b2``;
25288
+ const methods = this._getVisibleMethods();
25289
+ if (methods.length === 0)
25290
+ return b2`<p style="color: var(--t-muted); padding: var(--space-md);">
25291
+ No methods available.
25292
+ </p>`;
25293
+ const hasTools = methods.some((m3) => !m3.isTemplate);
25294
+ const hasPrompts = methods.some((m3) => m3.isTemplate);
25295
+ const title = hasTools && hasPrompts ? "Methods & Prompts" : hasPrompts ? "Prompts" : "Methods";
25296
+ return b2`
25297
+ ${this._renderAnchorNav()}
25298
+ <div id="photon-methods" class="bento-methods">
25299
+ <h3 class="bento-section-title">${title}</h3>
25300
+ <div class="cards-grid">
25301
+ ${methods.map(
25302
+ (method) => b2`
25303
+ <method-card
25304
+ .method=${method}
25305
+ .photonName=${this._selectedPhoton.name}
25306
+ .selected=${this._selectedMethod?.name === method.name}
25307
+ @select=${(e8) => {
25308
+ this._selectedMethod = e8.detail.method;
25309
+ this._view = "form";
25310
+ this._mainTab = "methods";
25311
+ this._updateRoute();
25312
+ }}
25313
+ ></method-card>
25314
+ `
25315
+ )}
25316
+ </div>
25317
+ </div>
25318
+ <div id="photon-prompts" class="bento-bottom-grid">
25319
+ ${this._renderPromptsSection()} ${this._renderResourcesSection()}
25320
+ </div>
25321
+ `;
25322
+ }
25186
25323
  _renderContent() {
25187
25324
  if (this._view === "source") {
25188
25325
  return this._renderSourceView();
@@ -25740,62 +25877,72 @@ ${photon.errorMessage || "Unknown error"}</pre
25740
25877
  ` : ""}
25741
25878
  <div
25742
25879
  class="glass-panel"
25743
- style="padding: 0; overflow: hidden; min-height: calc(100vh - 80px); position: relative; ${hasMultipleUIs ? "border-radius: 0 0 var(--radius-md) var(--radius-md);" : ""}"
25880
+ style="padding: 0; overflow: hidden; ${this._mainTab === "app" ? "flex: 1; display: flex; flex-direction: column;" : "min-height: calc(100vh - 80px);"} position: relative; ${hasMultipleUIs ? "border-radius: 0 0 var(--radius-md) var(--radius-md);" : ""}"
25744
25881
  >
25745
25882
  <mcp-app-renderer
25746
25883
  .mcpName=${this._selectedPhoton.name}
25747
25884
  .appUri=${currentUri}
25748
25885
  .linkedTool=${linkedMethod?.name || ""}
25749
25886
  .theme=${this._theme}
25750
- style="height: calc(100vh - ${hasMultipleUIs ? "120px" : "80px"});"
25887
+ style="${this._mainTab === "app" ? "flex: 1; height: 100%;" : `height: calc(100vh - ${hasMultipleUIs ? "120px" : "80px"});`}"
25751
25888
  ></mcp-app-renderer>
25752
25889
  </div>
25753
25890
 
25754
- ${this._renderPhotonToolbar()} ${this._renderAnchorNav()}
25755
- <div id="photon-methods" class="bento-methods">
25756
- <h3 class="bento-section-title">
25757
- ${(() => {
25891
+ ${this._mainTab !== "app" ? b2`
25892
+ ${this._renderAnchorNav()}
25893
+ <div id="photon-methods" class="bento-methods">
25894
+ <h3 class="bento-section-title">
25895
+ ${(() => {
25758
25896
  const visible = this._getVisibleMethods();
25759
25897
  const hasTools = visible.some((m3) => !m3.isTemplate);
25760
25898
  const hasPrompts = visible.some((m3) => m3.isTemplate);
25761
25899
  return hasTools && hasPrompts ? "Methods & Prompts" : hasPrompts ? "Prompts" : "Methods";
25762
25900
  })()}
25763
- </h3>
25764
- ${this._getVisibleMethods().length > 0 ? b2`
25765
- <div class="cards-grid">
25766
- ${this._getVisibleMethods().map(
25901
+ </h3>
25902
+ ${this._getVisibleMethods().length > 0 ? b2`
25903
+ <div class="cards-grid">
25904
+ ${this._getVisibleMethods().map(
25767
25905
  (method) => b2`
25768
- <method-card
25769
- .method=${method}
25770
- .photonName=${this._selectedPhoton.name}
25771
- .selected=${this._selectedMethod?.name === method.name}
25772
- @select=${(e8) => {
25906
+ <method-card
25907
+ .method=${method}
25908
+ .photonName=${this._selectedPhoton.name}
25909
+ .selected=${this._selectedMethod?.name === method.name}
25910
+ @select=${(e8) => {
25773
25911
  this._selectedMethod = e8.detail.method;
25774
25912
  this._view = "form";
25775
25913
  this._updateRoute();
25776
25914
  }}
25777
- ></method-card>
25778
- `
25915
+ ></method-card>
25916
+ `
25779
25917
  )}
25780
- </div>
25781
- ` : ""}
25782
- </div>
25783
- <div id="photon-prompts" class="bento-bottom-grid">
25784
- ${this._renderPromptsSection()} ${this._renderResourcesSection()}
25785
- </div>
25918
+ </div>
25919
+ ` : ""}
25920
+ </div>
25921
+ <div id="photon-prompts" class="bento-bottom-grid">
25922
+ ${this._renderPromptsSection()} ${this._renderResourcesSection()}
25923
+ </div>
25924
+ ` : ""}
25786
25925
  `;
25787
25926
  }
25788
25927
  if (this._view === "form" && this._selectedMethod) {
25789
25928
  const isAppMain = this._selectedPhoton.isApp && this._selectedMethod.name === "main";
25790
25929
  if (isAppMain && !this._selectedMethod.linkedUi) {
25791
25930
  const otherMethods = this._getVisibleMethods().filter((m3) => m3.name !== "main");
25931
+ const appTabActive = this._mainTab === "app";
25792
25932
  return b2`
25793
25933
  <app-layout
25794
25934
  .photonName=${this._selectedPhoton.name}
25795
25935
  .photonIcon=${this._selectedPhoton.appEntry?.icon || "\u{1F4F1}"}
25936
+ .hideBelow=${appTabActive}
25796
25937
  >
25797
- <div slot="app" style="min-height: calc(100vh - 140px);">
25798
- <div class="glass-panel" style="min-height: calc(100vh - 140px); overflow: hidden;">
25938
+ <div
25939
+ slot="app"
25940
+ style="${appTabActive ? "height: calc(100vh - 80px);" : "min-height: calc(100vh - 140px);"}"
25941
+ >
25942
+ <div
25943
+ class="glass-panel"
25944
+ style="${appTabActive ? "height: calc(100vh - 80px);" : "min-height: calc(100vh - 140px);"} overflow: hidden;"
25945
+ >
25799
25946
  ${this._renderMethodBody({
25800
25947
  photon: this._selectedPhoton,
25801
25948
  method: this._selectedMethod,
@@ -25810,44 +25957,45 @@ ${photon.errorMessage || "Unknown error"}</pre
25810
25957
  </div>
25811
25958
  </div>
25812
25959
  <div slot="popout" style="height: 100%;"></div>
25813
- <div slot="below-fold">
25814
- ${this._renderPhotonToolbar()} ${this._renderAnchorNav()}
25815
- ${otherMethods.length > 0 ? b2`
25816
- <div id="photon-methods" class="bento-methods">
25817
- <h3 class="bento-section-title">
25818
- ${(() => {
25960
+ ${appTabActive ? b2`<div slot="below-fold"></div>` : b2`<div slot="below-fold">
25961
+ ${this._renderAnchorNav()}
25962
+ ${otherMethods.length > 0 ? b2`
25963
+ <div id="photon-methods" class="bento-methods">
25964
+ <h3 class="bento-section-title">
25965
+ ${(() => {
25819
25966
  const hasTools = otherMethods.some((m3) => !m3.isTemplate);
25820
25967
  const hasPrompts = otherMethods.some((m3) => m3.isTemplate);
25821
25968
  return hasTools && hasPrompts ? "Methods & Prompts" : hasPrompts ? "Prompts" : "Methods";
25822
25969
  })()}
25823
- </h3>
25824
- <div class="cards-grid">
25825
- ${otherMethods.map(
25970
+ </h3>
25971
+ <div class="cards-grid">
25972
+ ${otherMethods.map(
25826
25973
  (method) => b2`
25827
- <method-card
25828
- .method=${method}
25829
- .photonName=${this._selectedPhoton.name}
25830
- @select=${(e8) => this._handleMethodSelect(e8)}
25831
- @update-metadata=${this._handleMethodMetadataUpdate}
25832
- ></method-card>
25833
- `
25974
+ <method-card
25975
+ .method=${method}
25976
+ .photonName=${this._selectedPhoton.name}
25977
+ @select=${(e8) => this._handleMethodSelect(e8)}
25978
+ @update-metadata=${this._handleMethodMetadataUpdate}
25979
+ ></method-card>
25980
+ `
25834
25981
  )}
25835
- </div>
25836
- </div>
25837
- ` : ""}
25838
- <div id="photon-prompts" class="bento-bottom-grid">
25839
- ${this._renderPromptsSection()} ${this._renderResourcesSection()}
25840
- </div>
25841
- </div>
25982
+ </div>
25983
+ </div>
25984
+ ` : ""}
25985
+ <div id="photon-prompts" class="bento-bottom-grid">
25986
+ ${this._renderPromptsSection()} ${this._renderResourcesSection()}
25987
+ </div>
25988
+ </div>`}
25842
25989
  </app-layout>
25843
25990
  `;
25844
25991
  }
25845
25992
  if (this._selectedMethod.linkedUi) {
25846
25993
  const otherMethods = isAppMain ? this._getVisibleMethods().filter((m3) => m3.name !== "main") : [];
25847
25994
  const isExternalMCP = this._selectedPhoton.isExternalMCP;
25995
+ const appFillStyle = this._mainTab === "app" && isAppMain ? "height: 100%; min-height: 0;" : "height: calc(100vh - 140px);";
25848
25996
  const appRenderer = this._isExecuting ? b2`
25849
25997
  <div
25850
- style="display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; height: calc(100vh - 140px);"
25998
+ style="display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; ${appFillStyle}"
25851
25999
  >
25852
26000
  <span class="spinner"></span>
25853
26001
  <span style="color: var(--t-muted); font-size: 13px;">
@@ -25860,7 +26008,7 @@ ${photon.errorMessage || "Unknown error"}</pre
25860
26008
  .appUri=${`ui://${this._selectedPhoton.name}/${this._selectedMethod.linkedUi}`}
25861
26009
  .linkedTool=${this._selectedMethod.name}
25862
26010
  .theme=${this._theme}
25863
- style="height: calc(100vh - 140px);"
26011
+ style="${appFillStyle}"
25864
26012
  ></mcp-app-renderer>
25865
26013
  ` : b2`
25866
26014
  <custom-ui-renderer
@@ -25870,7 +26018,7 @@ ${photon.errorMessage || "Unknown error"}</pre
25870
26018
  .theme=${this._theme}
25871
26019
  .initialResult=${this._lastResult}
25872
26020
  .revision=${this._customUiRevision}
25873
- style="height: calc(100vh - 140px);"
26021
+ style="${appFillStyle}"
25874
26022
  ></custom-ui-renderer>
25875
26023
  `;
25876
26024
  if (isAppMain) {
@@ -25888,7 +26036,7 @@ ${photon.errorMessage || "Unknown error"}</pre
25888
26036
  ${this._splitPanels.map(
25889
26037
  (panel) => b2`
25890
26038
  <div
25891
- style="flex: 1; min-width: 0; min-height: 0; overflow: auto; background: var(--bg-panel);"
26039
+ style="flex: 1; min-width: 0; min-height: 0; overflow: hidden; background: var(--bg-panel);"
25892
26040
  >
25893
26041
  ${panel.type === "method" ? this._renderSinglePanel(this._buildAdditionalPanelOpts(panel)) : this._renderSourcePanel(panel.id)}
25894
26042
  </div>
@@ -25897,46 +26045,54 @@ ${photon.errorMessage || "Unknown error"}</pre
25897
26045
  </div>
25898
26046
  `;
25899
26047
  }
26048
+ const appTabActive2 = this._mainTab === "app";
25900
26049
  return b2`
25901
26050
  <app-layout
25902
26051
  .photonName=${this._selectedPhoton.name}
25903
26052
  .photonIcon=${this._selectedPhoton.appEntry?.icon || "\u{1F4F1}"}
26053
+ .hideBelow=${appTabActive2}
25904
26054
  >
25905
- <div slot="app" style="min-height: calc(100vh - 140px);">${appRenderer}</div>
26055
+ <div
26056
+ slot="app"
26057
+ style="${appTabActive2 ? "height: 100%; min-height: 0; display: flex; flex-direction: column;" : "min-height: calc(100vh - 140px);"}"
26058
+ >
26059
+ ${appRenderer}
26060
+ </div>
25906
26061
  <!-- Popout slot is lazily populated when app-layout toggles popout mode.
25907
26062
  Eagerly creating a second renderer causes Safari to load two
25908
26063
  iframes simultaneously (one with zero dimensions), leading to
25909
26064
  blank screens. -->
25910
26065
  <div slot="popout" style="height: 100%;"></div>
25911
- <div slot="below-fold">
25912
- ${this._renderPhotonToolbar()} ${this._renderAnchorNav()}
25913
- ${otherMethods.length > 0 ? b2`
25914
- <div id="photon-methods" class="bento-methods">
25915
- <h3 class="bento-section-title">
25916
- ${(() => {
26066
+ ${appTabActive2 ? b2`<div slot="below-fold"></div>` : b2`<div slot="below-fold">
26067
+ ${this._renderAnchorNav()}
26068
+ ${otherMethods.length > 0 ? b2`
26069
+ <div id="photon-methods" class="bento-methods">
26070
+ <h3 class="bento-section-title">
26071
+ ${(() => {
25917
26072
  const hasTools = otherMethods.some((m3) => !m3.isTemplate);
25918
26073
  const hasPrompts = otherMethods.some((m3) => m3.isTemplate);
25919
26074
  return hasTools && hasPrompts ? "Methods & Prompts" : hasPrompts ? "Prompts" : "Methods";
25920
26075
  })()}
25921
- </h3>
25922
- <div class="cards-grid">
25923
- ${otherMethods.map(
26076
+ </h3>
26077
+ <div class="cards-grid">
26078
+ ${otherMethods.map(
25924
26079
  (method) => b2`
25925
- <method-card
25926
- .method=${method}
25927
- .photonName=${this._selectedPhoton.name}
25928
- @select=${(e8) => this._handleMethodSelect(e8)}
25929
- @update-metadata=${this._handleMethodMetadataUpdate}
25930
- ></method-card>
25931
- `
26080
+ <method-card
26081
+ .method=${method}
26082
+ .photonName=${this._selectedPhoton.name}
26083
+ .editable=${!!this._selectedPhoton.editable && !this._selectedPhoton.isExternalMCP}
26084
+ @select=${(e8) => this._handleMethodSelect(e8)}
26085
+ @update-metadata=${this._handleMethodMetadataUpdate}
26086
+ ></method-card>
26087
+ `
25932
26088
  )}
25933
- </div>
25934
- </div>
25935
- ` : ""}
25936
- <div id="photon-prompts" class="bento-bottom-grid">
25937
- ${this._renderPromptsSection()} ${this._renderResourcesSection()}
25938
- </div>
25939
- </div>
26089
+ </div>
26090
+ </div>
26091
+ ` : ""}
26092
+ <div id="photon-prompts" class="bento-bottom-grid">
26093
+ ${this._renderPromptsSection()} ${this._renderResourcesSection()}
26094
+ </div>
26095
+ </div>`}
25940
26096
  </app-layout>
25941
26097
  `;
25942
26098
  }
@@ -25976,7 +26132,7 @@ ${photon.errorMessage || "Unknown error"}</pre
25976
26132
  ${this._splitPanels.map(
25977
26133
  (panel) => b2`
25978
26134
  <div
25979
- style="flex: 1; min-width: 0; min-height: 0; overflow: auto; background: var(--bg-panel);"
26135
+ style="flex: 1; min-width: 0; min-height: 0; overflow: hidden; background: var(--bg-panel);"
25980
26136
  >
25981
26137
  ${panel.type === "method" ? this._renderSinglePanel(this._buildAdditionalPanelOpts(panel)) : this._renderSourcePanel(panel.id)}
25982
26138
  </div>
@@ -26012,8 +26168,7 @@ ${photon.errorMessage || "Unknown error"}</pre
26012
26168
  return b2` ${this._renderMethodContent()} `;
26013
26169
  }
26014
26170
  return b2`
26015
- ${this._renderPhotonToolbar()} ${this._editingIcon ? this._renderEmojiPicker() : ""}
26016
- ${this._renderAnchorNav()}
26171
+ ${this._editingIcon ? this._renderEmojiPicker() : ""} ${this._renderAnchorNav()}
26017
26172
 
26018
26173
  <div id="photon-methods" class="bento-methods">
26019
26174
  <h3 class="bento-section-title">
@@ -26086,6 +26241,50 @@ ${photon.errorMessage || "Unknown error"}</pre
26086
26241
  _closeSidebar() {
26087
26242
  this._sidebarVisible = false;
26088
26243
  }
26244
+ _handleSplitResizeStart(e8) {
26245
+ e8.preventDefault();
26246
+ const divider = e8.currentTarget;
26247
+ divider.setPointerCapture(e8.pointerId);
26248
+ divider.classList.add("dragging");
26249
+ const container = divider.parentElement;
26250
+ const containerRect = container.getBoundingClientRect();
26251
+ const startX = e8.clientX;
26252
+ const primaryPanel = divider.previousElementSibling;
26253
+ const startWidth = primaryPanel.getBoundingClientRect().width;
26254
+ const onMove = (moveEvent) => {
26255
+ const delta = moveEvent.clientX - startX;
26256
+ const minWidth = 200;
26257
+ const maxWidth = containerRect.width - 200 - 5;
26258
+ this._splitPrimaryWidth = Math.min(maxWidth, Math.max(minWidth, startWidth + delta));
26259
+ };
26260
+ const onUp = () => {
26261
+ divider.classList.remove("dragging");
26262
+ divider.removeEventListener("pointermove", onMove);
26263
+ divider.removeEventListener("pointerup", onUp);
26264
+ };
26265
+ divider.addEventListener("pointermove", onMove);
26266
+ divider.addEventListener("pointerup", onUp);
26267
+ }
26268
+ _handleSidebarResizeStart(e8) {
26269
+ e8.preventDefault();
26270
+ const handle = e8.currentTarget;
26271
+ handle.setPointerCapture(e8.pointerId);
26272
+ handle.classList.add("dragging");
26273
+ const startX = e8.clientX;
26274
+ const startWidth = this._sidebarWidth;
26275
+ const onMove = (moveEvent) => {
26276
+ const newWidth = Math.min(500, Math.max(200, startWidth + moveEvent.clientX - startX));
26277
+ this._sidebarWidth = newWidth;
26278
+ };
26279
+ const onUp = () => {
26280
+ handle.classList.remove("dragging");
26281
+ localStorage.setItem("beam-sidebar-width", String(this._sidebarWidth));
26282
+ handle.removeEventListener("pointermove", onMove);
26283
+ handle.removeEventListener("pointerup", onUp);
26284
+ };
26285
+ handle.addEventListener("pointermove", onMove);
26286
+ handle.addEventListener("pointerup", onUp);
26287
+ }
26089
26288
  _handlePhotonSelectMobile(e8) {
26090
26289
  this._closeSidebar();
26091
26290
  void this._handlePhotonSelect(e8);
@@ -26152,6 +26351,7 @@ ${photon.errorMessage || "Unknown error"}</pre
26152
26351
  }
26153
26352
  if (this._selectedPhoton.isExternalMCP && this._selectedPhoton.hasMcpApp) {
26154
26353
  this._view = "mcp-app";
26354
+ this._mainTab = "app";
26155
26355
  this._updateRoute();
26156
26356
  return;
26157
26357
  }
@@ -26179,18 +26379,20 @@ ${photon.errorMessage || "Unknown error"}</pre
26179
26379
  }
26180
26380
  this._selectedMethod = this._selectedPhoton.appEntry;
26181
26381
  this._view = "form";
26382
+ this._mainTab = "app";
26182
26383
  this._updateRoute();
26183
26384
  this._maybeAutoInvoke(this._selectedPhoton.appEntry);
26184
26385
  return;
26185
26386
  } else {
26186
26387
  this._view = "list";
26388
+ this._mainTab = "methods";
26187
26389
  }
26188
26390
  this._updateRoute();
26189
26391
  }
26190
26392
  /** Fetch available instances for a stateful photon from the server */
26191
26393
  async _fetchInstances(photonName) {
26192
26394
  try {
26193
- const res = await fetch(`/api/instances/${photonName}`, {
26395
+ const res = await fetch(`/api/instances/${encodeURIComponent(photonName)}`, {
26194
26396
  signal: AbortSignal.timeout(1e4)
26195
26397
  });
26196
26398
  if (res.ok) {
@@ -26316,6 +26518,7 @@ ${photon.errorMessage || "Unknown error"}</pre
26316
26518
  return b2`<p>${cleaned}</p>`;
26317
26519
  }
26318
26520
  _renderMethodContent() {
26521
+ const showBackButton = this._mainTab === "methods" || !this._selectedPhoton?.isApp;
26319
26522
  if (this._isHtmlUiMode()) {
26320
26523
  return b2`
26321
26524
  <div class="glass-panel html-ui-panel" style="padding: 0; overflow: hidden;">
@@ -26336,10 +26539,10 @@ ${photon.errorMessage || "Unknown error"}</pre
26336
26539
  }
26337
26540
  if (this._splitPanels.length > 0) {
26338
26541
  return b2`
26339
- <div style="display: flex; gap: 1px; height: 100%; overflow: hidden; width: 100%;">
26542
+ <div style="display: flex; height: 100%; overflow: hidden; width: 100%;">
26340
26543
  <!-- Primary Panel -->
26341
26544
  <div
26342
- style="flex: 1; min-width: 0; min-height: 0; overflow: auto; background: var(--bg-panel);"
26545
+ style="${this._splitPrimaryWidth != null ? `width: ${this._splitPrimaryWidth}px; flex-shrink: 0;` : "flex: 1;"} min-width: 0; min-height: 0; overflow: auto; background: var(--bg-panel);"
26343
26546
  >
26344
26547
  ${this._renderSinglePanel({
26345
26548
  photon: this._selectedPhoton,
@@ -26368,7 +26571,9 @@ ${photon.errorMessage || "Unknown error"}</pre
26368
26571
  showDelete: false,
26369
26572
  showHelp: !this._selectedPhoton?.isExternalMCP
26370
26573
  }),
26371
- onOverflowSelect: (id2) => this._handleOverflowAction(id2)
26574
+ onOverflowSelect: (id2) => this._handleOverflowAction(id2),
26575
+ onBack: showBackButton ? () => void this._handleBackFromMethod() : void 0,
26576
+ backLabel: this._selectedPhoton?.name
26372
26577
  })}
26373
26578
  </div>
26374
26579
 
@@ -26376,7 +26581,11 @@ ${photon.errorMessage || "Unknown error"}</pre
26376
26581
  ${this._splitPanels.map(
26377
26582
  (panel) => b2`
26378
26583
  <div
26379
- style="flex: 1; min-width: 0; min-height: 0; overflow: auto; background: var(--bg-panel);"
26584
+ class="split-divider"
26585
+ @pointerdown=${(e8) => this._handleSplitResizeStart(e8)}
26586
+ ></div>
26587
+ <div
26588
+ style="flex: 1; min-width: 0; min-height: 0; overflow: hidden; background: var(--bg-panel);"
26380
26589
  >
26381
26590
  ${panel.type === "method" ? this._renderSinglePanel(this._buildAdditionalPanelOpts(panel)) : this._renderSourcePanel(panel.id)}
26382
26591
  </div>
@@ -26421,7 +26630,9 @@ ${photon.errorMessage || "Unknown error"}</pre
26421
26630
  showDelete: false,
26422
26631
  showHelp: !this._selectedPhoton?.isExternalMCP
26423
26632
  }),
26424
- onOverflowSelect: (id2) => this._handleOverflowAction(id2)
26633
+ onOverflowSelect: (id2) => this._handleOverflowAction(id2),
26634
+ onBack: showBackButton ? () => void this._handleBackFromMethod() : void 0,
26635
+ backLabel: this._selectedPhoton?.name
26425
26636
  });
26426
26637
  }
26427
26638
  /** Render a single panel with self-contained header */
@@ -26437,6 +26648,33 @@ ${photon.errorMessage || "Unknown error"}</pre
26437
26648
  class="panel-header"
26438
26649
  style="display: flex; align-items: center; gap: 8px; padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid var(--border-glass); flex-shrink: 0; position: relative;"
26439
26650
  >
26651
+ <!-- Back button -->
26652
+ ${opts.onBack ? b2`<button
26653
+ @click=${() => opts.onBack()}
26654
+ style="padding: 0; width: 24px; height: 24px; background: none; border: 1px solid var(--border-glass); border-radius: var(--radius-xs, 4px); color: var(--t-muted); cursor: pointer; display: flex; align-items: center; justify-content: center; flex-shrink: 0; transition: all 0.15s ease;"
26655
+ @mouseenter=${(e8) => {
26656
+ e8.target.style.color = "var(--t-primary)";
26657
+ e8.target.style.borderColor = "var(--accent-primary)";
26658
+ }}
26659
+ @mouseleave=${(e8) => {
26660
+ e8.target.style.color = "var(--t-muted)";
26661
+ e8.target.style.borderColor = "var(--border-glass)";
26662
+ }}
26663
+ title="Back to ${opts.backLabel || "methods"}"
26664
+ >
26665
+ <svg
26666
+ width="14"
26667
+ height="14"
26668
+ viewBox="0 0 24 24"
26669
+ fill="none"
26670
+ stroke="currentColor"
26671
+ stroke-width="2"
26672
+ stroke-linecap="round"
26673
+ stroke-linejoin="round"
26674
+ >
26675
+ <path d="m15 18-6-6 6-6" />
26676
+ </svg>
26677
+ </button>` : ""}
26440
26678
  <!-- LED dot (stateful/live indicator) -->
26441
26679
  ${opts.isStateful ? b2`<span
26442
26680
  style="width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: ${opts.isLive ? "var(--color-success, #22c55e)" : "var(--t-tertiary, #666)"}; box-shadow: ${opts.isLive ? "0 0 6px var(--color-success, #22c55e)" : "none"};"
@@ -26517,9 +26755,7 @@ ${photon.errorMessage || "Unknown error"}</pre
26517
26755
  _renderMethodBody(opts) {
26518
26756
  const hasParams = !!opts.method?.params?.properties && Object.keys(opts.method.params.properties).length > 0;
26519
26757
  return b2`
26520
- <div
26521
- style="display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: auto; scrollbar-gutter: stable;"
26522
- >
26758
+ <div style="display: flex; flex-direction: column; flex: 1; min-height: 0;">
26523
26759
  ${opts.appSurface ? "" : this._renderDescription(opts.method.description)}
26524
26760
  ${opts.appSurface && !hasParams ? "" : b2`
26525
26761
  <invoke-form
@@ -26629,6 +26865,7 @@ ${photon.errorMessage || "Unknown error"}</pre
26629
26865
  /** Close all split panels and return to single-panel mode */
26630
26866
  _closeSecondPanel() {
26631
26867
  this._splitPanels = [];
26868
+ this._splitPrimaryWidth = null;
26632
26869
  this._methodPickerOpen = false;
26633
26870
  this._methodPickerPanelId = null;
26634
26871
  this._updateRoute();
@@ -26676,17 +26913,11 @@ ${photon.errorMessage || "Unknown error"}</pre
26676
26913
  const panel = this._splitPanels.find((p5) => p5.id === panelId);
26677
26914
  if (!panel || panel.type !== "method" || !panel.method) return;
26678
26915
  this._updatePanel(panelId, { executing: true, result: null, progress: null, formParams: args });
26916
+ const progressToken = `panel_${panelId}_${Date.now()}`;
26917
+ this._panelProgressTokens.set(progressToken, panelId);
26679
26918
  try {
26680
26919
  const toolName = `${this._selectedPhoton.name}/${panel.method.name}`;
26681
- const result = await mcpClient.callTool(
26682
- toolName,
26683
- args,
26684
- void 0,
26685
- panel.instance || this._currentInstance,
26686
- (progress) => {
26687
- this._updatePanel(panelId, { progress });
26688
- }
26689
- );
26920
+ const result = await mcpClient.callTool(toolName, args, progressToken);
26690
26921
  this._updatePanel(panelId, {
26691
26922
  result: mcpClient.parseToolResult(result),
26692
26923
  executing: false,
@@ -26699,6 +26930,8 @@ ${photon.errorMessage || "Unknown error"}</pre
26699
26930
  executing: false,
26700
26931
  progress: null
26701
26932
  });
26933
+ } finally {
26934
+ this._panelProgressTokens.delete(progressToken);
26702
26935
  }
26703
26936
  }
26704
26937
  /** Change the method in a split panel */
@@ -26805,7 +27038,8 @@ ${photon.errorMessage || "Unknown error"}</pre
26805
27038
  void this._runTests();
26806
27039
  break;
26807
27040
  case "help":
26808
- this._showPhotonHelp = true;
27041
+ this._mainTab = "help";
27042
+ void this._loadPhotonHelp();
26809
27043
  break;
26810
27044
  default:
26811
27045
  this._handleContextAction(new CustomEvent("context-action", { detail: { action: id2 } }));
@@ -27474,6 +27708,61 @@ ${photon.errorMessage || "Unknown error"}</pre
27474
27708
  _closePhotonHelp() {
27475
27709
  this._showPhotonHelp = false;
27476
27710
  }
27711
+ /** Render the inline help view (used as a tab, not a modal) */
27712
+ _renderPhotonHelpView() {
27713
+ const markdown = this._photonHelpLoading ? this._generatePhotonHelpMarkdown() : this._photonHelpMarkdown || this._generatePhotonHelpMarkdown();
27714
+ let htmlContent = markdown;
27715
+ if (window.marked) {
27716
+ const mermaidBlocks = [];
27717
+ let processed = markdown.replace(
27718
+ /```mermaid\s*\n([\s\S]*?)```/g,
27719
+ (_match, code) => {
27720
+ const id2 = `help-mermaid-${Math.random().toString(36).substr(2, 9)}`;
27721
+ mermaidBlocks.push({ id: id2, code: code.trim() });
27722
+ return `<div data-mermaid-id="${id2}" style="min-height: 80px; display: flex; align-items: center; justify-content: center; color: var(--t-muted);">Loading diagram...</div>`;
27723
+ }
27724
+ );
27725
+ htmlContent = window.marked.parse(processed);
27726
+ if (mermaidBlocks.length > 0 && window.mermaid) {
27727
+ const mermaid = window.mermaid;
27728
+ const isDark = this.getAttribute("data-theme") !== "light";
27729
+ mermaid.initialize({ startOnLoad: false, theme: isDark ? "dark" : "default" });
27730
+ requestAnimationFrame(() => {
27731
+ for (const { id: id2, code } of mermaidBlocks) {
27732
+ const el2 = this.shadowRoot?.querySelector(`[data-mermaid-id="${id2}"]`);
27733
+ if (el2) {
27734
+ mermaid.render(id2 + "-svg", code).then(({ svg: svg2 }) => {
27735
+ el2.innerHTML = svg2;
27736
+ el2.style.minHeight = "";
27737
+ el2.style.background = isDark ? "hsla(220, 15%, 18%, 0.8)" : "hsla(0, 0%, 97%, 0.8)";
27738
+ el2.style.borderRadius = "8px";
27739
+ el2.style.padding = "12px";
27740
+ }).catch(() => {
27741
+ el2.textContent = "Diagram rendering failed";
27742
+ });
27743
+ }
27744
+ }
27745
+ });
27746
+ }
27747
+ }
27748
+ return b2`
27749
+ <div
27750
+ style="display: flex; flex-direction: column; height: 100%; overflow: auto; padding: var(--space-lg);"
27751
+ >
27752
+ <div style="max-width: 700px; width: 100%;">
27753
+ <h2 class="text-gradient" style="margin: 0 0 var(--space-md) 0;">
27754
+ Help
27755
+ ${this._photonHelpLoading ? b2`<span style="font-size: 0.7em; opacity: 0.6; margin-left: 8px;"
27756
+ >Loading...</span
27757
+ >` : ""}
27758
+ </h2>
27759
+ <div class="markdown-body" style="color: var(--t-default);">
27760
+ ${window.marked ? b2`${o5(htmlContent)}` : b2`<pre style="white-space: pre-wrap;">${markdown}</pre>`}
27761
+ </div>
27762
+ </div>
27763
+ </div>
27764
+ `;
27765
+ }
27477
27766
  _generatePhotonHelpMarkdown() {
27478
27767
  if (!this._selectedPhoton) return "";
27479
27768
  const photon = this._selectedPhoton;
@@ -27607,7 +27896,8 @@ ${photon.errorMessage || "Unknown error"}</pre
27607
27896
  const hasInstallSource = !!this._selectedPhoton?.installSource;
27608
27897
  const isStateful = !!this._selectedPhoton?.stateful;
27609
27898
  const hasSettings = !!this._selectedPhoton?.hasSettings;
27610
- const sourceMode = isExternalMCP ? "hidden" : this._view === "source" ? "edit" : hasPath && !this._selectedPhoton?.internal ? "source" : "hidden";
27899
+ const isEditable = !!this._selectedPhoton?.editable && !isExternalMCP;
27900
+ const sourceMode = isExternalMCP ? "hidden" : this._view === "source" ? "edit" : hasPath && !this._selectedPhoton?.internal && isEditable ? "source" : "hidden";
27611
27901
  return b2`
27612
27902
  <context-bar
27613
27903
  .photon=${this._selectedPhoton}
@@ -27619,17 +27909,17 @@ ${photon.errorMessage || "Unknown error"}</pre
27619
27909
  .instances=${this._instances}
27620
27910
  .instanceSelectorMode=${this._instanceSelectorMode}
27621
27911
  .autoInstance=${this._autoInstance}
27622
- .sourceMode=${sourceMode}
27623
- .hasSettings=${hasSettings && !isExternalMCP}
27912
+ .sourceMode=${"hidden"}
27913
+ .hasSettings=${false}
27624
27914
  .overflowItems=${this._buildOverflowItems({
27625
27915
  showRefresh: !isExternalMCP,
27626
27916
  showEdit: false,
27627
27917
  showUpgrade: !!this._selectedPhoton?.hasUpdate,
27628
- showRename: !isExternalMCP,
27918
+ showRename: isEditable,
27629
27919
  showViewSource: false,
27630
- showFork: hasInstallSource && !isExternalMCP,
27920
+ showFork: !isEditable && !isExternalMCP,
27631
27921
  showContribute: hasInstallSource && !isExternalMCP,
27632
- showDelete: !isExternalMCP,
27922
+ showDelete: isEditable,
27633
27923
  showHelp: !isExternalMCP
27634
27924
  })}
27635
27925
  @context-action=${this._handleContextAction}
@@ -27773,6 +28063,7 @@ ${photon.errorMessage || "Unknown error"}</pre
27773
28063
  _renderPhotonHeader() {
27774
28064
  if (!this._selectedPhoton) return "";
27775
28065
  const isApp = this._selectedPhoton.isApp;
28066
+ const isEditable = !!this._selectedPhoton.editable && !this._selectedPhoton.isExternalMCP;
27776
28067
  const methods = this._selectedPhoton.methods || [];
27777
28068
  const templateCount = methods.filter((m3) => m3.isTemplate).length;
27778
28069
  const toolCount = methods.filter((m3) => !m3.isTemplate).length;
@@ -27785,42 +28076,42 @@ ${photon.errorMessage || "Unknown error"}</pre
27785
28076
  const displayIcon = customIcon || defaultIcon;
27786
28077
  return b2`
27787
28078
  <header class="photon-header">
27788
- <button
27789
- type="button"
27790
- class="photon-icon-large editable ${isApp ? "" : "mcp-icon"}"
27791
- @click=${this._startEditingIcon}
27792
- title="Click to change icon"
27793
- aria-label="Change icon"
27794
- >
27795
- ${displayIcon}
27796
- </button>
28079
+ ${isEditable ? b2`<button
28080
+ type="button"
28081
+ class="photon-icon-large editable ${isApp ? "" : "mcp-icon"}"
28082
+ @click=${this._startEditingIcon}
28083
+ title="Click to change icon"
28084
+ aria-label="Change icon"
28085
+ >
28086
+ ${displayIcon}
28087
+ </button>` : b2`<span class="photon-icon-large ${isApp ? "" : "mcp-icon"}">${displayIcon}</span>`}
27797
28088
  ${this._editingIcon ? this._renderEmojiPicker() : ""}
27798
28089
  <div class="photon-header-info">
27799
28090
  <h1 class="photon-header-name">${this._selectedPhoton.name}</h1>
27800
- ${this._editingDescription ? b2`
27801
- <p class="photon-header-desc editable editing">
27802
- <input
27803
- class="editable-input"
27804
- type="text"
27805
- .value=${this._editedDescription}
27806
- placeholder="Add a description..."
27807
- @input=${(e8) => this._editedDescription = e8.target.value}
27808
- @blur=${this._saveDescription}
27809
- @keydown=${this._handleDescriptionKeydown}
27810
- autofocus
27811
- />
27812
- </p>
27813
- ` : b2`
27814
- <button
27815
- type="button"
27816
- class="photon-header-desc editable ${isGenericDesc ? "placeholder" : ""}"
27817
- @click=${this._startEditingDescription}
27818
- title="Click to edit description"
27819
- aria-label="Edit description"
27820
- >
27821
- ${isGenericDesc ? "Click to add a description..." : description}
27822
- </button>
27823
- `}
28091
+ ${isEditable ? this._editingDescription ? b2`
28092
+ <p class="photon-header-desc editable editing">
28093
+ <input
28094
+ class="editable-input"
28095
+ type="text"
28096
+ .value=${this._editedDescription}
28097
+ placeholder="Add a description..."
28098
+ @input=${(e8) => this._editedDescription = e8.target.value}
28099
+ @blur=${this._saveDescription}
28100
+ @keydown=${this._handleDescriptionKeydown}
28101
+ autofocus
28102
+ />
28103
+ </p>
28104
+ ` : b2`
28105
+ <button
28106
+ type="button"
28107
+ class="photon-header-desc editable ${isGenericDesc ? "placeholder" : ""}"
28108
+ @click=${this._startEditingDescription}
28109
+ title="Click to edit description"
28110
+ aria-label="Edit description"
28111
+ >
28112
+ ${isGenericDesc ? "Click to add a description..." : description}
28113
+ </button>
28114
+ ` : b2`<p class="photon-header-desc">${description}</p>`}
27824
28115
  <div class="photon-header-meta">
27825
28116
  ${isApp ? b2`<span class="photon-badge app">App</span>` : b2`<span class="photon-badge">MCP</span>`}
27826
28117
  ${templateCount > 0 && toolCount === 0 ? b2`<span class="photon-badge"
@@ -28286,14 +28577,133 @@ ${photon.errorMessage || "Unknown error"}</pre
28286
28577
  </div>
28287
28578
  `;
28288
28579
  }
28580
+ /** Render the settings view — a professional two-column settings panel */
28581
+ _renderSettingsView() {
28582
+ const photon = this._selectedPhoton;
28583
+ if (!photon) return "";
28584
+ const settingsMethod = photon.methods?.find((m3) => m3.name === "settings");
28585
+ if (!settingsMethod)
28586
+ return b2`<div style="padding: var(--space-xl); color: var(--t-muted); text-align: center;">
28587
+ No settings available for this photon.
28588
+ </div>`;
28589
+ const params = settingsMethod.params;
28590
+ const properties = params?.properties || {};
28591
+ const propEntries = Object.entries(properties);
28592
+ const hasResult = this._lastResult !== null;
28593
+ let statusEntries = [];
28594
+ if (hasResult) {
28595
+ try {
28596
+ const resultData = typeof this._lastResult === "string" ? JSON.parse(this._lastResult) : Array.isArray(this._lastResult) ? this._lastResult.find((c5) => c5.type === "text")?.text ? JSON.parse(this._lastResult.find((c5) => c5.type === "text").text) : this._lastResult : this._lastResult;
28597
+ if (resultData && typeof resultData === "object" && !Array.isArray(resultData)) {
28598
+ statusEntries = Object.entries(resultData).filter(([, v2]) => v2 !== null && v2 !== void 0).map(([k3, v2]) => [k3, String(v2)]);
28599
+ }
28600
+ } catch {
28601
+ }
28602
+ }
28603
+ return b2`
28604
+ <div style="padding: var(--space-lg); max-width: 900px; margin: 0 auto; width: 100%;">
28605
+ <!-- Settings Header -->
28606
+ <div style="margin-bottom: var(--space-xl);">
28607
+ <h2
28608
+ style="font-family: var(--font-display); font-size: var(--text-xl); font-weight: 700; color: var(--t-primary); margin: 0 0 4px 0;"
28609
+ >
28610
+ ${photon.name} Settings
28611
+ </h2>
28612
+ ${settingsMethod.description ? b2`<p
28613
+ style="color: var(--t-muted); font-size: var(--text-sm); margin: 0; line-height: 1.5;"
28614
+ >
28615
+ View or update photon configuration. Changes are applied immediately.
28616
+ </p>` : ""}
28617
+ </div>
28618
+
28619
+ <!-- Configuration Section -->
28620
+ ${propEntries.length > 0 ? b2`
28621
+ <div class="glass-panel" style="margin-bottom: var(--space-lg); overflow: hidden;">
28622
+ <div
28623
+ style="padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--border-glass); background: var(--bg-glass);"
28624
+ >
28625
+ <span
28626
+ style="font-family: var(--font-display); font-size: var(--text-sm); font-weight: 600; color: var(--t-primary); text-transform: uppercase; letter-spacing: 0.05em;"
28627
+ >Configuration</span
28628
+ >
28629
+ </div>
28630
+ <div class="method-detail" style="padding: 0;">
28631
+ <invoke-form
28632
+ .params=${params}
28633
+ .loading=${this._isExecuting}
28634
+ .photonName=${photon.name}
28635
+ .methodName=${"settings"}
28636
+ .rememberValues=${this._rememberFormValues}
28637
+ .sharedValues=${this._sharedFormParams ?? this._lastFormParams}
28638
+ .settingsLayout=${true}
28639
+ @submit=${(e8) => void this._handleExecute(e8)}
28640
+ @cancel=${() => {
28641
+ }}
28642
+ ></invoke-form>
28643
+ <div
28644
+ style="display: flex; justify-content: flex-end; padding: var(--space-sm) var(--space-md); border-top: 1px solid var(--border-glass);"
28645
+ >
28646
+ <button
28647
+ class="btn-primary"
28648
+ style="font-size: var(--text-sm); padding: 6px 20px;"
28649
+ @click=${(e8) => {
28650
+ const panel = e8.target.closest(".glass-panel");
28651
+ const form = panel?.querySelector("invoke-form");
28652
+ form?.handleSubmit();
28653
+ }}
28654
+ ?disabled=${this._isExecuting}
28655
+ >
28656
+ ${this._isExecuting ? b2`<span class="btn-loading"
28657
+ ><span class="spinner"></span>Saving...</span
28658
+ >` : "Save Settings"}
28659
+ </button>
28660
+ </div>
28661
+ </div>
28662
+ </div>
28663
+ ` : ""}
28664
+
28665
+ <!-- Status Section (from last result) -->
28666
+ ${statusEntries.length > 0 ? b2`
28667
+ <div class="glass-panel" style="overflow: hidden;">
28668
+ <div
28669
+ style="padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--border-glass); background: var(--bg-glass);"
28670
+ >
28671
+ <span
28672
+ style="font-family: var(--font-display); font-size: var(--text-sm); font-weight: 600; color: var(--t-primary); text-transform: uppercase; letter-spacing: 0.05em;"
28673
+ >Status</span
28674
+ >
28675
+ </div>
28676
+ <div style="padding: 0;">
28677
+ ${statusEntries.map(
28678
+ ([key, value], i7) => b2`
28679
+ <div
28680
+ style="display: grid; grid-template-columns: 200px 1fr; border-bottom: ${i7 < statusEntries.length - 1 ? "1px solid var(--border-glass)" : "none"};"
28681
+ >
28682
+ <div
28683
+ style="padding: 10px var(--space-md); font-size: var(--text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--t-muted); background: var(--bg-glass);"
28684
+ >
28685
+ ${key.replace(/([A-Z])/g, " $1").replace(/_/g, " ").trim()}
28686
+ </div>
28687
+ <div
28688
+ style="padding: 10px var(--space-md); font-size: var(--text-sm); color: var(--t-primary); word-break: break-word;"
28689
+ >
28690
+ ${value}
28691
+ </div>
28692
+ </div>
28693
+ `
28694
+ )}
28695
+ </div>
28696
+ </div>
28697
+ ` : ""}
28698
+ </div>
28699
+ `;
28700
+ }
28289
28701
  /** Render source code as an inline view (not a modal) — Phase 2 */
28290
28702
  _renderSourceView() {
28291
28703
  if (!this._sourceData) {
28292
28704
  return b2`
28293
- ${this._renderPhotonToolbar({ showConfigure: false, showCopyConfig: false })}
28294
28705
  <div
28295
- class="glass-panel"
28296
- style="padding: var(--space-xl); text-align: center; color: var(--t-muted);"
28706
+ style="display: flex; align-items: center; justify-content: center; height: 100%; color: var(--t-muted);"
28297
28707
  >
28298
28708
  Loading source...
28299
28709
  </div>
@@ -28324,26 +28734,56 @@ ${photon.errorMessage || "Unknown error"}</pre
28324
28734
  if (Prism && Prism.languages[language2]) {
28325
28735
  highlightedCode = Prism.highlight(this._sourceData.code, Prism.languages[language2], language2);
28326
28736
  }
28737
+ const isProtected = !this._selectedPhoton?.editable;
28327
28738
  return b2`
28328
- ${this._renderPhotonToolbar({ showConfigure: false, showCopyConfig: false })}
28329
- <div
28330
- class="glass-panel"
28331
- style="margin-top: var(--space-md); display: flex; flex-direction: column; max-height: calc(100vh - 120px);"
28332
- >
28739
+ <div style="display: flex; flex-direction: column; height: 100%;">
28333
28740
  <div
28334
- style="display: flex; justify-content: space-between; align-items: center; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--border-glass); flex-shrink: 0;"
28741
+ style="display: flex; justify-content: space-between; align-items: center; padding: 6px var(--space-md); border-bottom: 1px solid var(--border-glass); flex-shrink: 0; background: var(--bg-panel);"
28335
28742
  >
28336
- <div style="font-family: var(--font-mono); font-size: 0.85rem; color: var(--t-muted);">
28337
- ${filename}
28743
+ <div style="display: flex; align-items: center; gap: 8px;">
28744
+ <div style="font-family: var(--font-mono); font-size: 0.85rem; color: var(--t-muted);">
28745
+ ${filename}
28746
+ </div>
28747
+ ${isProtected ? b2`<span
28748
+ style="font-size: var(--text-2xs); padding: 2px 6px; background: var(--bg-glass-strong); border: 1px solid var(--border-glass); border-radius: var(--radius-xs); color: var(--t-muted); text-transform: uppercase; letter-spacing: 0.05em;"
28749
+ >Protected</span
28750
+ >` : ""}
28751
+ </div>
28752
+ <div style="display: flex; gap: 6px; align-items: center;">
28753
+ ${isProtected ? b2`<button
28754
+ class="action-btn"
28755
+ style="display: inline-flex; align-items: center; background: var(--bg-glass); border: 1px solid var(--accent-secondary); color: var(--accent-secondary); padding: 4px 10px; border-radius: var(--radius-sm); cursor: pointer; font-size: var(--text-xs);"
28756
+ @click=${this._handleFork}
28757
+ title="Fork to create an editable local copy"
28758
+ >
28759
+ <svg
28760
+ width="12"
28761
+ height="12"
28762
+ viewBox="0 0 24 24"
28763
+ fill="none"
28764
+ stroke="currentColor"
28765
+ stroke-width="2"
28766
+ stroke-linecap="round"
28767
+ stroke-linejoin="round"
28768
+ style="margin-right: 3px;"
28769
+ >
28770
+ <circle cx="12" cy="18" r="3" />
28771
+ <circle cx="6" cy="6" r="3" />
28772
+ <circle cx="18" cy="6" r="3" />
28773
+ <path d="M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9" />
28774
+ <path d="M12 12v3" />
28775
+ </svg>
28776
+ Fork
28777
+ </button>` : ""}
28778
+ <button
28779
+ class="action-btn"
28780
+ style="display: inline-flex; align-items: center; background: var(--bg-glass); border: 1px solid var(--border-glass); color: var(--t-muted); padding: 4px 10px; border-radius: var(--radius-sm); cursor: pointer; font-size: var(--text-xs);"
28781
+ @click=${this._copySourceCode}
28782
+ title="Copy source code"
28783
+ >
28784
+ ${clipboard} Copy
28785
+ </button>
28338
28786
  </div>
28339
- <button
28340
- class="action-btn"
28341
- style="background: var(--bg-glass); border: 1px solid var(--border-glass); color: var(--t-muted); padding: 4px 10px; border-radius: var(--radius-sm); cursor: pointer; font-size: var(--text-xs);"
28342
- @click=${this._copySourceCode}
28343
- title="Copy source code"
28344
- >
28345
- ${clipboard} Copy
28346
- </button>
28347
28787
  </div>
28348
28788
  <pre
28349
28789
  class="language-${language2}"
@@ -28358,7 +28798,6 @@ ${photon.errorMessage || "Unknown error"}</pre
28358
28798
  font-size: 0.85rem;
28359
28799
  line-height: 1.6;
28360
28800
  tab-size: 2;
28361
- border-radius: 0 0 var(--radius-md) var(--radius-md);
28362
28801
  "
28363
28802
  ><code class="language-${language2}" style="display: block; overflow-x: visible;">${Prism ? o5(highlightedCode) : this._sourceData.code}</code></pre>
28364
28803
  </div>
@@ -28417,7 +28856,7 @@ ${photon.errorMessage || "Unknown error"}</pre
28417
28856
  </div>
28418
28857
  </div>
28419
28858
  <div style="display: flex; gap: var(--space-sm);">
28420
- ${this._selectedPhoton?.path && !this._selectedPhoton?.isExternalMCP ? b2`
28859
+ ${this._selectedPhoton?.editable && !this._selectedPhoton?.isExternalMCP ? b2`
28421
28860
  <button
28422
28861
  class="toolbar-btn"
28423
28862
  style="padding: 6px 12px; font-size: 0.85rem; background: var(--accent-primary); border-color: var(--accent-primary); color: white;"
@@ -28612,11 +29051,31 @@ BeamApp.styles = [
28612
29051
  }
28613
29052
 
28614
29053
  .sidebar-area {
28615
- width: 300px;
29054
+ width: var(--sidebar-width, 300px);
28616
29055
  flex-shrink: 0;
28617
29056
  z-index: 10;
28618
29057
  display: flex;
28619
29058
  flex-direction: column;
29059
+ position: relative;
29060
+ overflow: visible;
29061
+ }
29062
+
29063
+ .sidebar-resize-handle {
29064
+ position: absolute;
29065
+ right: -3px;
29066
+ top: 0;
29067
+ bottom: 0;
29068
+ width: 6px;
29069
+ cursor: col-resize;
29070
+ z-index: 20;
29071
+ background: transparent;
29072
+ transition: background 0.15s;
29073
+ }
29074
+
29075
+ .sidebar-resize-handle:hover,
29076
+ .sidebar-resize-handle.dragging {
29077
+ background: var(--accent-primary);
29078
+ opacity: 0.5;
28620
29079
  }
28621
29080
 
28622
29081
  :host(.focus-mode) .sidebar-area {
@@ -28842,10 +29301,20 @@ BeamApp.styles = [
28842
29301
  flex: 1;
28843
29302
  min-width: 0;
28844
29303
  position: relative;
29304
+ display: flex;
29305
+ flex-direction: column;
29306
+ overflow: hidden;
29307
+ }
29308
+
29309
+ .main-content-scroll {
29310
+ flex: 1;
29311
+ min-height: 0;
28845
29312
  overflow-y: auto;
28846
29313
  overflow-x: hidden;
28847
29314
  padding: var(--space-lg);
28848
29315
  scrollbar-gutter: stable;
29316
+ display: flex;
29317
+ flex-direction: column;
28849
29318
  }
28850
29319
 
28851
29320
  /* Page transition when switching photons */
@@ -28866,9 +29335,9 @@ BeamApp.styles = [
28866
29335
 
28867
29336
  .main-toolbar {
28868
29337
  display: flex;
28869
- justify-content: space-between;
28870
29338
  align-items: center;
28871
- margin: calc(-1 * var(--space-lg) + 4px) calc(-1 * var(--space-lg) + 4px) 4px;
29339
+ gap: var(--space-sm);
29340
+ margin-bottom: 8px;
28872
29341
  flex-shrink: 0;
28873
29342
  }
28874
29343
 
@@ -28897,9 +29366,22 @@ BeamApp.styles = [
28897
29366
  margin-left: auto;
28898
29367
  }
28899
29368
 
29369
+ .beam-tab-btn.active {
29370
+ color: var(--accent-secondary);
29371
+ border-color: var(--accent-secondary);
29372
+ }
29373
+
29374
+ .tab-group-divider {
29375
+ width: 1px;
29376
+ height: 16px;
29377
+ background: var(--border-glass);
29378
+ margin: 0 2px;
29379
+ align-self: center;
29380
+ }
29381
+
28900
29382
  .cards-grid {
28901
29383
  display: grid;
28902
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
29384
+ grid-template-columns: repeat(auto-fill, minmax(280px, min(100%, 380px)));
28903
29385
  gap: var(--space-md);
28904
29386
  align-items: stretch;
28905
29387
  }
@@ -28951,7 +29433,7 @@ BeamApp.styles = [
28951
29433
  .anchor-nav {
28952
29434
  display: flex;
28953
29435
  gap: var(--space-md);
28954
- margin: var(--space-md) 0 var(--space-lg);
29436
+ margin: 0 0 var(--space-md);
28955
29437
  }
28956
29438
 
28957
29439
  .anchor-link {
@@ -28997,7 +29479,7 @@ BeamApp.styles = [
28997
29479
  display: flex;
28998
29480
  align-items: flex-start;
28999
29481
  gap: var(--space-lg);
29000
- margin-bottom: var(--space-xl);
29482
+ margin-bottom: var(--space-md);
29001
29483
  }
29002
29484
 
29003
29485
  .photon-icon-large {
@@ -30159,6 +30641,34 @@ BeamApp.styles = [
30159
30641
  margin-top: var(--space-md);
30160
30642
  }
30161
30643
 
30644
+ .split-divider {
30645
+ width: 5px;
30646
+ flex-shrink: 0;
30647
+ cursor: col-resize;
30648
+ background: var(--border-glass);
30649
+ position: relative;
30650
+ transition: background 0.15s;
30651
+ }
30652
+
30653
+ .split-divider::after {
30654
+ content: '';
30655
+ position: absolute;
30656
+ top: 50%;
30657
+ left: 50%;
30658
+ transform: translate(-50%, -50%);
30659
+ width: 1px;
30660
+ height: 32px;
30661
+ background: var(--t-muted);
30662
+ border-radius: 2px;
30663
+ opacity: 0.4;
30664
+ }
30665
+
30666
+ .split-divider:hover,
30667
+ .split-divider.dragging {
30668
+ background: var(--accent-primary);
30669
+ opacity: 0.6;
30670
+ }
30671
+
30162
30672
  .method-detail h2 {
30163
30673
  margin-top: 0;
30164
30674
  }
@@ -30394,6 +30904,9 @@ __decorateClass([
30394
30904
  __decorateClass([
30395
30905
  r5()
30396
30906
  ], BeamApp.prototype, "_sidebarVisible", 2);
30907
+ __decorateClass([
30908
+ r5()
30909
+ ], BeamApp.prototype, "_sidebarWidth", 2);
30397
30910
  __decorateClass([
30398
30911
  r5()
30399
30912
  ], BeamApp.prototype, "_focusMode", 2);
@@ -30553,6 +31066,12 @@ __decorateClass([
30553
31066
  __decorateClass([
30554
31067
  r5()
30555
31068
  ], BeamApp.prototype, "_methodPickerPanelId", 2);
31069
+ __decorateClass([
31070
+ r5()
31071
+ ], BeamApp.prototype, "_splitPrimaryWidth", 2);
31072
+ __decorateClass([
31073
+ r5()
31074
+ ], BeamApp.prototype, "_mainTab", 2);
30556
31075
  __decorateClass([
30557
31076
  e7("beam-sidebar")
30558
31077
  ], BeamApp.prototype, "_sidebar", 2);
@@ -30568,6 +31087,12 @@ __decorateClass([
30568
31087
  __decorateClass([
30569
31088
  r5()
30570
31089
  ], BeamApp.prototype, "_forkOriginRepo", 2);
31090
+ __decorateClass([
31091
+ r5()
31092
+ ], BeamApp.prototype, "_forkRequireNewName", 2);
31093
+ __decorateClass([
31094
+ r5()
31095
+ ], BeamApp.prototype, "_forkSuggestedName", 2);
30571
31096
  __decorateClass([
30572
31097
  r5()
30573
31098
  ], BeamApp.prototype, "_forkTargets", 2);
@@ -30587,6 +31112,11 @@ var BeamSidebar = class extends i4 {
30587
31112
  this.reconnecting = false;
30588
31113
  this.updatesAvailable = 0;
30589
31114
  this.pendingApprovals = 0;
31115
+ this.mainTab = "methods";
31116
+ this.isApp = false;
31117
+ this.hasSettings = false;
31118
+ this.isExternalMCP = false;
31119
+ this.hasPath = false;
30590
31120
  this._searchQuery = "";
30591
31121
  this._showFavoritesOnly = false;
30592
31122
  this._favorites = /* @__PURE__ */ new Set();
@@ -30676,6 +31206,11 @@ var BeamSidebar = class extends i4 {
30676
31206
  super.updated(changedProps);
30677
31207
  if (changedProps.has("selectedPhoton")) {
30678
31208
  this._ensureActiveSectionOpen();
31209
+ if (this.selectedPhoton) {
31210
+ this._scrollPhotonIntoView(this.selectedPhoton, false);
31211
+ } else {
31212
+ this._scrollSidebarToTop();
31213
+ }
30679
31214
  }
30680
31215
  }
30681
31216
  get _filteredPhotons() {
@@ -30751,6 +31286,25 @@ var BeamSidebar = class extends i4 {
30751
31286
  title="${this.connected ? "Connected" : this.reconnecting ? "Reconnecting..." : "Disconnected"}"
30752
31287
  ></span>
30753
31288
  </button>
31289
+ <button
31290
+ class="sidebar-minimize-btn"
31291
+ @click=${() => this.dispatchEvent(new CustomEvent("toggle-focus"))}
31292
+ title="Minimize sidebar"
31293
+ >
31294
+ <svg
31295
+ width="14"
31296
+ height="14"
31297
+ viewBox="0 0 24 24"
31298
+ fill="none"
31299
+ stroke="currentColor"
31300
+ stroke-width="2"
31301
+ stroke-linecap="round"
31302
+ stroke-linejoin="round"
31303
+ >
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" />
31306
+ </svg>
31307
+ </button>
30754
31308
  </div>
30755
31309
  <div class="search-box" role="search">
30756
31310
  <input
@@ -30783,29 +31337,30 @@ var BeamSidebar = class extends i4 {
30783
31337
  </div>
30784
31338
  </div>
30785
31339
 
30786
- ${(() => {
31340
+ <div class="sidebar-scroll">
31341
+ ${(() => {
30787
31342
  const apps = this._sortByRecency(this._apps);
30788
31343
  const configured = this._sortByRecency(this._configured);
30789
31344
  return b2`
30790
- ${apps.length > 0 ? this._renderSection(
31345
+ ${apps.length > 0 ? this._renderSection(
30791
31346
  "apps",
30792
31347
  "APPS",
30793
31348
  apps,
30794
31349
  (p5) => p5.isExternalMCP ? this._renderExternalMCPItem(p5) : this._renderPhotonItem(p5, "app")
30795
31350
  ) : ""}
30796
- ${configured.length > 0 ? this._renderSection(
31351
+ ${configured.length > 0 ? this._renderSection(
30797
31352
  "photons",
30798
31353
  "PHOTONS",
30799
31354
  configured,
30800
31355
  (p5) => this._renderPhotonItem(p5, "configured")
30801
31356
  ) : ""}
30802
- `;
31357
+ `;
30803
31358
  })()}
30804
- ${(() => {
31359
+ ${(() => {
30805
31360
  const needsConfig = this._needsSetup.filter((p5) => p5.errorReason !== "load-error");
30806
31361
  const loadErrors = this._needsSetup.filter((p5) => p5.errorReason === "load-error");
30807
31362
  return b2`
30808
- ${needsConfig.length > 0 ? this._renderSection(
31363
+ ${needsConfig.length > 0 ? this._renderSection(
30809
31364
  "config",
30810
31365
  "NEEDS CONFIGURATION",
30811
31366
  needsConfig,
@@ -30813,7 +31368,7 @@ var BeamSidebar = class extends i4 {
30813
31368
  "attention",
30814
31369
  warning
30815
31370
  ) : ""}
30816
- ${loadErrors.length > 0 ? this._renderSection(
31371
+ ${loadErrors.length > 0 ? this._renderSection(
30817
31372
  "errors",
30818
31373
  "LOAD ERRORS",
30819
31374
  loadErrors,
@@ -30821,35 +31376,36 @@ var BeamSidebar = class extends i4 {
30821
31376
  "attention",
30822
31377
  xMark
30823
31378
  ) : ""}
30824
- `;
31379
+ `;
30825
31380
  })()}
30826
- ${this._nonAppExternalMCPs.length > 0 ? this._renderSection(
31381
+ ${this._nonAppExternalMCPs.length > 0 ? this._renderSection(
30827
31382
  "mcps",
30828
31383
  "MCPS",
30829
31384
  this._sortByRecency(this._nonAppExternalMCPs),
30830
31385
  (mcp) => this._renderExternalMCPItem(mcp)
30831
31386
  ) : ""}
30832
- ${this._apps.length === 0 && this._configured.length === 0 && this._needsSetup.length === 0 && this._nonAppExternalMCPs.length === 0 ? b2`
30833
- <div class="empty-state">
30834
- ${this._searchQuery.trim() ? b2`
30835
- <div class="empty-icon">${search}</div>
30836
- <div class="empty-title">No results</div>
30837
- <div class="empty-hint">No photons match "${this._searchQuery}"</div>
30838
- ` : b2`
30839
- <div class="empty-icon">${packageBox}</div>
30840
- <div class="empty-title">No photons yet</div>
30841
- <div class="empty-hint">
30842
- Add photons from the marketplace or create your own
30843
- </div>
30844
- <button
30845
- class="empty-action"
30846
- @click=${() => this.dispatchEvent(new CustomEvent("marketplace"))}
30847
- >
30848
- ${marketplace} Browse Marketplace
30849
- </button>
30850
- `}
30851
- </div>
30852
- ` : ""}
31387
+ ${this._apps.length === 0 && this._configured.length === 0 && this._needsSetup.length === 0 && this._nonAppExternalMCPs.length === 0 ? b2`
31388
+ <div class="empty-state">
31389
+ ${this._searchQuery.trim() ? b2`
31390
+ <div class="empty-icon">${search}</div>
31391
+ <div class="empty-title">No results</div>
31392
+ <div class="empty-hint">No photons match "${this._searchQuery}"</div>
31393
+ ` : b2`
31394
+ <div class="empty-icon">${packageBox}</div>
31395
+ <div class="empty-title">No photons yet</div>
31396
+ <div class="empty-hint">
31397
+ Add photons from the marketplace or create your own
31398
+ </div>
31399
+ <button
31400
+ class="empty-action"
31401
+ @click=${() => this.dispatchEvent(new CustomEvent("marketplace"))}
31402
+ >
31403
+ ${marketplace} Browse Marketplace
31404
+ </button>
31405
+ `}
31406
+ </div>
31407
+ ` : ""}
31408
+ </div>
30853
31409
  </nav>
30854
31410
 
30855
31411
  <div class="sidebar-footer">
@@ -30866,14 +31422,6 @@ var BeamSidebar = class extends i4 {
30866
31422
  <span class="approval-badge">${this.pendingApprovals}</span>
30867
31423
  </button>
30868
31424
  ` : ""}
30869
- <button
30870
- class="footer-link"
30871
- @click=${() => this.dispatchEvent(new CustomEvent("diagnostics", { bubbles: true, composed: true }))}
30872
- title="Server diagnostics"
30873
- aria-label="Show diagnostics"
30874
- >
30875
- ${activity}
30876
- </button>
30877
31425
  <button
30878
31426
  class="footer-link"
30879
31427
  @click=${() => this._showShortcuts()}
@@ -30950,7 +31498,7 @@ var BeamSidebar = class extends i4 {
30950
31498
  class="photon-list motion-stagger ${collapsed ? "collapsed" : ""}"
30951
31499
  role="listbox"
30952
31500
  aria-labelledby=${headerId}
30953
- style="max-height: ${collapsed ? "0" : items.length * 52 + "px"}"
31501
+ style="max-height: ${collapsed ? "0" : this._estimateSectionHeight(items) + "px"}"
30954
31502
  >
30955
31503
  ${items.map(renderItem)}
30956
31504
  </ul>
@@ -30974,41 +31522,46 @@ var BeamSidebar = class extends i4 {
30974
31522
  const isLight = this.theme === "light";
30975
31523
  initialsStyle = isLight ? `background: hsl(${hue2}, 30%, 90%); color: hsl(${hue2}, 50%, 35%);` : `background: hsl(${hue2}, 35%, 22%); color: hsl(${hue2}, 60%, 75%);`;
30976
31524
  }
31525
+ const isSelected = this.selectedPhoton === photon.name;
30977
31526
  return b2`
30978
31527
  <li
30979
- class="photon-item ${this.selectedPhoton === photon.name ? "active" : ""} ${photon.internal ? "internal" : ""} ${this._isPhotonWarm(photon.name) ? "warmth" : ""}"
31528
+ class="photon-item ${isSelected ? "active" : ""} ${photon.internal ? "internal" : ""} ${this._isPhotonWarm(photon.name) ? "warmth" : ""}"
30980
31529
  role="option"
30981
- aria-selected="${this.selectedPhoton === photon.name}"
31530
+ aria-selected="${isSelected}"
30982
31531
  tabindex="0"
30983
31532
  @click=${() => this._selectPhoton(photon)}
30984
31533
  @keydown=${(e8) => e8.key === "Enter" && this._selectPhoton(photon)}
30985
31534
  title="${photon.description || photon.name}${photon.path ? `
30986
31535
  ${photon.path}` : ""}"
30987
31536
  >
30988
- <div
30989
- class="photon-icon ${isEmoji ? "emoji-icon" : ""}"
30990
- style="${initialsStyle}"
30991
- aria-hidden="true"
30992
- >
30993
- ${displayIcon}
30994
- </div>
30995
- <div class="photon-info">
30996
- <div class="photon-name">${photon.name}</div>
30997
- ${photon.internal ? b2`<span class="internal-badge">System</span>` : ""}
31537
+ <div class="photon-item-body">
31538
+ <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
+ <div class="photon-info">
31547
+ <div class="photon-name">${photon.name}</div>
31548
+ ${photon.internal ? b2`<span class="internal-badge">System</span>` : ""}
31549
+ </div>
31550
+ <button
31551
+ class="star-btn ${isFavorited ? "favorited" : ""}"
31552
+ @click=${(e8) => this._toggleFavorite(e8, photon.name)}
31553
+ title="${isFavorited ? "Remove from favorites" : "Add to favorites"}"
31554
+ aria-label="${isFavorited ? `Remove ${photon.name} from favorites` : `Add ${photon.name} to favorites`}"
31555
+ aria-pressed="${isFavorited}"
31556
+ >
31557
+ ${isFavorited ? starFilled : starOutline}
31558
+ </button>
31559
+ ${isUnconfigured ? photon.errorReason === "load-error" ? b2`<span class="method-count error" aria-label="Error loading">×</span>` : b2`<span class="method-count unconfigured" aria-label="Needs configuration"
31560
+ >?</span
31561
+ >` : this._renderCountsPill(photon, methodCount)}
31562
+ </div>
31563
+ ${isSelected ? this._renderInlineViewTabs() : ""}
30998
31564
  </div>
30999
- ${""}
31000
- <button
31001
- class="star-btn ${isFavorited ? "favorited" : ""}"
31002
- @click=${(e8) => this._toggleFavorite(e8, photon.name)}
31003
- title="${isFavorited ? "Remove from favorites" : "Add to favorites"}"
31004
- aria-label="${isFavorited ? `Remove ${photon.name} from favorites` : `Add ${photon.name} to favorites`}"
31005
- aria-pressed="${isFavorited}"
31006
- >
31007
- ${isFavorited ? starFilled : starOutline}
31008
- </button>
31009
- ${isUnconfigured ? photon.errorReason === "load-error" ? b2`<span class="method-count error" aria-label="Error loading">×</span>` : b2`<span class="method-count unconfigured" aria-label="Needs configuration"
31010
- >?</span
31011
- >` : this._renderCountsPill(photon, methodCount)}
31012
31565
  </li>
31013
31566
  `;
31014
31567
  }
@@ -31017,46 +31570,120 @@ ${photon.path}` : ""}"
31017
31570
  const isConnected = mcp.connected !== false;
31018
31571
  const displayIcon = mcp.icon || plug;
31019
31572
  const isFavorited = this._favorites.has(mcp.name);
31573
+ const isSelected = this.selectedPhoton === mcp.name;
31020
31574
  return b2`
31021
31575
  <li
31022
- class="photon-item ${this.selectedPhoton === mcp.name ? "active" : ""} ${!isConnected ? "disconnected" : ""}"
31576
+ class="photon-item ${isSelected ? "active" : ""} ${!isConnected ? "disconnected" : ""}"
31023
31577
  role="option"
31024
- aria-selected="${this.selectedPhoton === mcp.name}"
31578
+ aria-selected="${isSelected}"
31025
31579
  tabindex="0"
31026
31580
  @click=${() => this._selectPhoton(mcp)}
31027
31581
  @keydown=${(e8) => e8.key === "Enter" && this._selectPhoton(mcp)}
31028
31582
  title="${mcp.description || "External MCP server"}${mcp.errorMessage ? `
31029
31583
  \u26A0\uFE0F ${mcp.errorMessage}` : ""}"
31030
31584
  >
31031
- <div class="photon-icon external-mcp-icon" aria-hidden="true">${displayIcon}</div>
31032
- <div class="photon-info">
31033
- <div class="photon-name">${mcp.name}</div>
31585
+ <div class="photon-item-body">
31586
+ <div class="photon-main-row">
31587
+ <div class="photon-icon external-mcp-icon" aria-hidden="true">${displayIcon}</div>
31588
+ <div class="photon-info">
31589
+ <div class="photon-name">${mcp.name}</div>
31590
+ </div>
31591
+ <button
31592
+ class="star-btn ${isFavorited ? "favorited" : ""}"
31593
+ @click=${(e8) => this._toggleFavorite(e8, mcp.name)}
31594
+ title="${isFavorited ? "Remove from favorites" : "Add to favorites"}"
31595
+ aria-label="${isFavorited ? `Remove ${mcp.name} from favorites` : `Add ${mcp.name} to favorites`}"
31596
+ aria-pressed="${isFavorited}"
31597
+ >
31598
+ ${isFavorited ? starFilled : starOutline}
31599
+ </button>
31600
+ ${!isConnected ? b2`
31601
+ <span class="disconnect-badge" title="${mcp.errorMessage || "Disconnected"}"
31602
+ >Offline</span
31603
+ >
31604
+ <button
31605
+ class="reconnect-btn"
31606
+ @click=${(e8) => this._reconnectMCP(e8, mcp.name)}
31607
+ title="Reconnect"
31608
+ aria-label="Reconnect ${mcp.name}"
31609
+ >
31610
+
31611
+ </button>
31612
+ ` : this._renderCountsPill(mcp, methodCount)}
31613
+ </div>
31614
+ ${isSelected ? this._renderInlineViewTabs() : ""}
31034
31615
  </div>
31035
- <button
31036
- class="star-btn ${isFavorited ? "favorited" : ""}"
31037
- @click=${(e8) => this._toggleFavorite(e8, mcp.name)}
31038
- title="${isFavorited ? "Remove from favorites" : "Add to favorites"}"
31039
- aria-label="${isFavorited ? `Remove ${mcp.name} from favorites` : `Add ${mcp.name} to favorites`}"
31040
- aria-pressed="${isFavorited}"
31041
- >
31042
- ${isFavorited ? starFilled : starOutline}
31043
- </button>
31044
- ${!isConnected ? b2`
31045
- <span class="disconnect-badge" title="${mcp.errorMessage || "Disconnected"}"
31046
- >Offline</span
31047
- >
31048
- <button
31049
- class="reconnect-btn"
31050
- @click=${(e8) => this._reconnectMCP(e8, mcp.name)}
31051
- title="Reconnect"
31052
- aria-label="Reconnect ${mcp.name}"
31053
- >
31054
-
31055
- </button>
31056
- ` : this._renderCountsPill(mcp, methodCount)}
31057
31616
  </li>
31058
31617
  `;
31059
31618
  }
31619
+ _renderInlineViewTabs() {
31620
+ const appTabIcon = b2`<svg
31621
+ width="14"
31622
+ height="14"
31623
+ viewBox="0 0 24 24"
31624
+ fill="none"
31625
+ stroke="currentColor"
31626
+ stroke-width="2"
31627
+ stroke-linecap="round"
31628
+ stroke-linejoin="round"
31629
+ aria-hidden="true"
31630
+ >
31631
+ <rect x="3" y="3" width="18" height="18" rx="2" />
31632
+ <path d="M3 9h18" />
31633
+ <path d="M9 21V9" />
31634
+ </svg>`;
31635
+ const methodsTabIcon = b2`<svg
31636
+ width="14"
31637
+ height="14"
31638
+ viewBox="0 0 24 24"
31639
+ fill="none"
31640
+ stroke="currentColor"
31641
+ stroke-width="2"
31642
+ stroke-linecap="round"
31643
+ stroke-linejoin="round"
31644
+ aria-hidden="true"
31645
+ >
31646
+ <rect x="3" y="3" width="7" height="7" />
31647
+ <rect x="14" y="3" width="7" height="7" />
31648
+ <rect x="3" y="14" width="7" height="7" />
31649
+ <rect x="14" y="14" width="7" height="7" />
31650
+ </svg>`;
31651
+ const tabs = [
31652
+ ...this.isApp ? [{ id: "app", label: "App", icon: appTabIcon }] : [],
31653
+ { id: "methods", label: "Methods", icon: methodsTabIcon },
31654
+ { id: "log", label: "Activity", icon: activity },
31655
+ ...this.hasSettings ? [{ id: "settings", label: "Settings", icon: settings }] : [],
31656
+ ...this.hasPath && !this.isExternalMCP ? [{ id: "source", label: "Source", icon: source }] : [],
31657
+ { id: "help", label: "Help", icon: docs }
31658
+ ];
31659
+ return b2`
31660
+ <div class="photon-view-tabs" role="tablist" aria-label="Selected photon views">
31661
+ ${tabs.map(
31662
+ (tab) => b2`
31663
+ <button
31664
+ class="photon-view-tab ${this.mainTab === tab.id ? "active" : ""}"
31665
+ role="tab"
31666
+ aria-selected=${String(this.mainTab === tab.id)}
31667
+ title=${tab.label}
31668
+ aria-label=${tab.label}
31669
+ @click=${(e8) => {
31670
+ e8.stopPropagation();
31671
+ this._emitTabChange(tab.id);
31672
+ }}
31673
+ >
31674
+ ${tab.icon}
31675
+ </button>
31676
+ `
31677
+ )}
31678
+ </div>
31679
+ `;
31680
+ }
31681
+ _estimateSectionHeight(items) {
31682
+ return items.reduce((height, item) => {
31683
+ const isSelected = item.name === this.selectedPhoton;
31684
+ return height + (isSelected ? 92 : 52);
31685
+ }, 0);
31686
+ }
31060
31687
  _reconnectMCP(e8, mcpName) {
31061
31688
  e8.stopPropagation();
31062
31689
  this.dispatchEvent(
@@ -31102,6 +31729,9 @@ ${photon.path}` : ""}"
31102
31729
  })
31103
31730
  );
31104
31731
  }
31732
+ _emitTabChange(tab) {
31733
+ this.dispatchEvent(new CustomEvent("tab-change", { detail: { tab } }));
31734
+ }
31105
31735
  _handleSearch(e8) {
31106
31736
  this._searchQuery = e8.target.value;
31107
31737
  }
@@ -31159,6 +31789,9 @@ ${photon.path}` : ""}"
31159
31789
  return this._showFavoritesOnly;
31160
31790
  }
31161
31791
  scrollPhotonIntoView(name2) {
31792
+ this._scrollPhotonIntoView(name2, true);
31793
+ }
31794
+ _scrollPhotonIntoView(name2, flashHighlight) {
31162
31795
  void this.updateComplete.then(() => {
31163
31796
  const items = this.shadowRoot?.querySelectorAll(".photon-item");
31164
31797
  if (!items) return;
@@ -31166,13 +31799,23 @@ ${photon.path}` : ""}"
31166
31799
  const nameEl = item.querySelector(".photon-name");
31167
31800
  if (nameEl?.textContent?.trim() === name2) {
31168
31801
  item.scrollIntoView({ behavior: "smooth", block: "nearest" });
31169
- item.classList.add("flash-highlight");
31170
- setTimeout(() => item.classList.remove("flash-highlight"), 600);
31802
+ if (flashHighlight) {
31803
+ item.classList.add("flash-highlight");
31804
+ setTimeout(() => item.classList.remove("flash-highlight"), 600);
31805
+ }
31171
31806
  break;
31172
31807
  }
31173
31808
  }
31174
31809
  });
31175
31810
  }
31811
+ _scrollSidebarToTop() {
31812
+ void this.updateComplete.then(() => {
31813
+ const scrollEl = this.shadowRoot?.querySelector(".sidebar-scroll");
31814
+ if (scrollEl) {
31815
+ scrollEl.scrollTo({ top: 0, behavior: "smooth" });
31816
+ }
31817
+ });
31818
+ }
31176
31819
  /**
31177
31820
  * Check if a photon currently has a warmth indicator (notification received within last 5 seconds)
31178
31821
  */
@@ -31206,9 +31849,17 @@ BeamSidebar.styles = [
31206
31849
  flex-direction: column;
31207
31850
  height: 100%;
31208
31851
  color: var(--t-primary);
31852
+ overflow: visible;
31209
31853
  }
31210
31854
 
31211
31855
  .sidebar-content {
31856
+ flex: 1;
31857
+ overflow: hidden;
31858
+ display: flex;
31859
+ flex-direction: column;
31860
+ }
31861
+
31862
+ .sidebar-scroll {
31212
31863
  flex: 1;
31213
31864
  overflow-y: auto;
31214
31865
  padding-right: 4px;
@@ -31300,6 +31951,7 @@ BeamSidebar.styles = [
31300
31951
  .header {
31301
31952
  padding: var(--space-md);
31302
31953
  border-bottom: 1px solid var(--border-glass);
31954
+ flex-shrink: 0;
31303
31955
  }
31304
31956
 
31305
31957
  .header-row {
@@ -31409,6 +32061,27 @@ BeamSidebar.styles = [
31409
32061
  position: relative;
31410
32062
  }
31411
32063
 
32064
+ .sidebar-minimize-btn {
32065
+ width: 28px;
32066
+ height: 28px;
32067
+ border-radius: var(--radius-sm);
32068
+ background: transparent;
32069
+ border: none;
32070
+ color: var(--t-muted);
32071
+ cursor: pointer;
32072
+ display: flex;
32073
+ align-items: center;
32074
+ justify-content: center;
32075
+ transition: all 0.15s ease;
32076
+ padding: 0;
32077
+ flex-shrink: 0;
32078
+ }
32079
+
32080
+ .sidebar-minimize-btn:hover {
32081
+ color: var(--t-primary);
32082
+ background: var(--bg-glass);
32083
+ }
32084
+
31412
32085
  input {
31413
32086
  padding: var(--space-sm) var(--space-md);
31414
32087
  }
@@ -31502,6 +32175,9 @@ BeamSidebar.styles = [
31502
32175
  border-left: 2px solid var(--accent-primary);
31503
32176
  color: var(--accent-primary);
31504
32177
  font-weight: 500;
32178
+ align-items: stretch;
32179
+ padding-top: calc(var(--space-sm) + 2px);
32180
+ padding-bottom: calc(var(--space-sm) + 2px);
31505
32181
  }
31506
32182
 
31507
32183
  .photon-item.flash-highlight {
@@ -31571,6 +32247,25 @@ BeamSidebar.styles = [
31571
32247
  flex: 1;
31572
32248
  }
31573
32249
 
32250
+ .photon-item-body {
32251
+ min-width: 0;
32252
+ flex: 1;
32253
+ display: flex;
32254
+ flex-direction: column;
32255
+ gap: 8px;
32256
+ }
32257
+
32258
+ .photon-main-row {
32259
+ display: flex;
32260
+ align-items: center;
32261
+ gap: var(--space-sm);
32262
+ min-width: 0;
32263
+ }
32264
+
32265
+ .photon-main-row .photon-info {
32266
+ min-width: 0;
32267
+ }
32268
+
31574
32269
  .photon-name {
31575
32270
  font-family: var(--font-display);
31576
32271
  font-weight: 600;
@@ -31587,6 +32282,45 @@ BeamSidebar.styles = [
31587
32282
  text-overflow: ellipsis;
31588
32283
  }
31589
32284
 
32285
+ .photon-view-tabs {
32286
+ display: flex;
32287
+ align-items: center;
32288
+ gap: 4px;
32289
+ margin-left: calc(28px + var(--space-sm));
32290
+ }
32291
+
32292
+ .photon-view-tab {
32293
+ width: 26px;
32294
+ height: 26px;
32295
+ display: inline-flex;
32296
+ align-items: center;
32297
+ justify-content: center;
32298
+ border: 1px solid var(--border-glass);
32299
+ background: color-mix(in srgb, var(--bg-glass-strong) 82%, transparent);
32300
+ color: var(--t-muted);
32301
+ border-radius: var(--radius-sm);
32302
+ padding: 0;
32303
+ cursor: pointer;
32304
+ transition: all 0.15s ease;
32305
+ }
32306
+
32307
+ .photon-view-tab svg {
32308
+ width: 13px;
32309
+ height: 13px;
32310
+ }
32311
+
32312
+ .photon-view-tab:hover {
32313
+ color: var(--t-primary);
32314
+ border-color: color-mix(in srgb, var(--accent-primary) 38%, var(--border-glass));
32315
+ background: color-mix(in srgb, var(--accent-primary) 10%, var(--bg-glass-strong));
32316
+ }
32317
+
32318
+ .photon-view-tab.active {
32319
+ color: white;
32320
+ border-color: var(--accent-primary);
32321
+ background: color-mix(in srgb, var(--accent-primary) 78%, black 22%);
32322
+ }
32323
+
31590
32324
  .method-count {
31591
32325
  font-size: var(--text-2xs);
31592
32326
  padding: 2px 6px;
@@ -31887,6 +32621,10 @@ BeamSidebar.styles = [
31887
32621
  min-height: 44px;
31888
32622
  }
31889
32623
 
32624
+ .photon-view-tabs {
32625
+ margin-left: 0;
32626
+ }
32627
+
31890
32628
  .photon-item .star-btn {
31891
32629
  padding: var(--space-sm);
31892
32630
  opacity: 0.4;
@@ -31941,6 +32679,21 @@ __decorateClass([
31941
32679
  __decorateClass([
31942
32680
  n4({ type: Number })
31943
32681
  ], BeamSidebar.prototype, "pendingApprovals", 2);
32682
+ __decorateClass([
32683
+ n4({ type: String })
32684
+ ], BeamSidebar.prototype, "mainTab", 2);
32685
+ __decorateClass([
32686
+ n4({ type: Boolean })
32687
+ ], BeamSidebar.prototype, "isApp", 2);
32688
+ __decorateClass([
32689
+ n4({ type: Boolean })
32690
+ ], BeamSidebar.prototype, "hasSettings", 2);
32691
+ __decorateClass([
32692
+ n4({ type: Boolean })
32693
+ ], BeamSidebar.prototype, "isExternalMCP", 2);
32694
+ __decorateClass([
32695
+ n4({ type: Boolean })
32696
+ ], BeamSidebar.prototype, "hasPath", 2);
31944
32697
  __decorateClass([
31945
32698
  r5()
31946
32699
  ], BeamSidebar.prototype, "_searchQuery", 2);
@@ -31971,6 +32724,7 @@ var MethodCard = class extends i4 {
31971
32724
  constructor() {
31972
32725
  super(...arguments);
31973
32726
  this.photonName = "";
32727
+ this.editable = false;
31974
32728
  this._editingDescription = false;
31975
32729
  this._editingIcon = false;
31976
32730
  this._editedDescription = "";
@@ -32034,20 +32788,20 @@ var MethodCard = class extends i4 {
32034
32788
  ${this.method.icon}
32035
32789
  </div>
32036
32790
  ` : ""}
32037
- <span class="editable">
32791
+ <span class="${this.editable ? "editable" : ""}">
32038
32792
  <h3 class="title">
32039
32793
  <span class="title-name">${this.method.name}</span>${this._renderParamSignature()}
32040
32794
  </h3>
32041
- <span
32042
- class="edit-pencil"
32043
- role="button"
32044
- tabindex="0"
32045
- @click=${(e8) => this._handleNameEditClick(e8)}
32046
- @keydown=${(e8) => (e8.key === "Enter" || e8.key === " ") && (e8.preventDefault(), this._handleNameEditClick(e8))}
32047
- title="Rename method"
32048
- aria-label="Rename method"
32049
- >${pencil}</span
32050
- >
32795
+ ${this.editable ? b2`<span
32796
+ class="edit-pencil"
32797
+ role="button"
32798
+ tabindex="0"
32799
+ @click=${(e8) => this._handleNameEditClick(e8)}
32800
+ @keydown=${(e8) => (e8.key === "Enter" || e8.key === " ") && (e8.preventDefault(), this._handleNameEditClick(e8))}
32801
+ title="Rename method"
32802
+ aria-label="Rename method"
32803
+ >${pencil}</span
32804
+ >` : ""}
32051
32805
  </span>
32052
32806
  </div>
32053
32807
  ${this.method.isTemplate ? b2`<span class="badge prompt">Prompt</span>` : ""}
@@ -32087,21 +32841,24 @@ var MethodCard = class extends i4 {
32087
32841
  <span class="char-counter">${this._editedDescription.length}/500</span>
32088
32842
  </div>
32089
32843
  ` : b2`
32090
- <div class="editable" style="flex:1; align-items: flex-start;">
32844
+ <div
32845
+ class="${this.editable ? "editable" : ""}"
32846
+ style="flex:1; align-items: flex-start;"
32847
+ >
32091
32848
  <div class="description ${hasDescription ? "" : "placeholder"}" style="flex:1;">
32092
- ${hasDescription ? this._renderDescription(this.method.description) : "Add description..."}
32849
+ ${hasDescription ? this._renderDescription(this.method.description) : this.editable ? "Add description..." : ""}
32093
32850
  </div>
32094
- <span
32095
- class="edit-pencil"
32096
- role="button"
32097
- tabindex="0"
32098
- @click=${(e8) => this._handleDescriptionEditClick(e8)}
32099
- @keydown=${(e8) => (e8.key === "Enter" || e8.key === " ") && (e8.preventDefault(), this._handleDescriptionEditClick(e8))}
32100
- title="Edit description"
32101
- aria-label="Edit description"
32102
- style="margin-top: 2px;"
32103
- >${pencil}</span
32104
- >
32851
+ ${this.editable ? b2`<span
32852
+ class="edit-pencil"
32853
+ role="button"
32854
+ tabindex="0"
32855
+ @click=${(e8) => this._handleDescriptionEditClick(e8)}
32856
+ @keydown=${(e8) => (e8.key === "Enter" || e8.key === " ") && (e8.preventDefault(), this._handleDescriptionEditClick(e8))}
32857
+ title="Edit description"
32858
+ aria-label="Edit description"
32859
+ style="margin-top: 2px;"
32860
+ >${pencil}</span
32861
+ >` : ""}
32105
32862
  </div>
32106
32863
  `}
32107
32864
  </div>
@@ -32698,6 +33455,9 @@ __decorateClass([
32698
33455
  __decorateClass([
32699
33456
  n4({ type: String })
32700
33457
  ], MethodCard.prototype, "photonName", 2);
33458
+ __decorateClass([
33459
+ n4({ type: Boolean })
33460
+ ], MethodCard.prototype, "editable", 2);
32701
33461
  __decorateClass([
32702
33462
  r5()
32703
33463
  ], MethodCard.prototype, "_editingDescription", 2);
@@ -32812,6 +33572,7 @@ var InvokeForm = class extends i4 {
32812
33572
  this.methodName = "";
32813
33573
  this.rememberValues = false;
32814
33574
  this.sharedValues = null;
33575
+ this.settingsLayout = false;
32815
33576
  this._values = {};
32816
33577
  this._initialValues = {};
32817
33578
  this._passwordVisible = {};
@@ -32917,12 +33678,13 @@ var InvokeForm = class extends i4 {
32917
33678
  const result = await mcpClient.callTool(`${this.photonName}/${toolName}`, {});
32918
33679
  let values = [];
32919
33680
  let data = result;
32920
- if (result && Array.isArray(result.content)) {
32921
- if (result.isError) {
33681
+ const mcpResult = result;
33682
+ if (result && Array.isArray(mcpResult.content)) {
33683
+ if (mcpResult.isError) {
32922
33684
  hasUnresolved = true;
32923
33685
  continue;
32924
33686
  }
32925
- const textBlock = result.content.find((c5) => c5.type === "text");
33687
+ const textBlock = mcpResult.content.find((c5) => c5.type === "text");
32926
33688
  if (textBlock?.text) {
32927
33689
  try {
32928
33690
  data = JSON.parse(textBlock.text);
@@ -33022,6 +33784,42 @@ var InvokeForm = class extends i4 {
33022
33784
  const isRequired = Array.isArray(requiredList) ? requiredList.includes(key) : !!schema.required;
33023
33785
  const error2 = this._errors[key];
33024
33786
  const inputId = `field-${key}`;
33787
+ if (this.settingsLayout) {
33788
+ const isBoolean = schema.type === "boolean" || schema.type === '"boolean"';
33789
+ return b2`
33790
+ <div
33791
+ style="display: grid; grid-template-columns: 200px 1fr; border-bottom: 1px solid var(--border-glass); min-height: 48px;"
33792
+ >
33793
+ <div
33794
+ style="padding: 12px var(--space-md); display: flex; flex-direction: column; justify-content: center; background: var(--bg-glass);"
33795
+ >
33796
+ <label
33797
+ for=${inputId}
33798
+ style="font-size: var(--text-sm); font-weight: 600; color: var(--t-primary); margin: 0;"
33799
+ >
33800
+ ${formatLabel(key)}
33801
+ </label>
33802
+ ${schema.description ? b2`<span
33803
+ style="font-size: var(--text-2xs); color: var(--t-muted); margin-top: 2px; line-height: 1.3;"
33804
+ >${this._cleanDescription(schema.description, schema)}</span
33805
+ >` : ""}
33806
+ </div>
33807
+ <div
33808
+ style="padding: ${isBoolean ? "8px" : "6px"} var(--space-md); display: flex; align-items: center;"
33809
+ >
33810
+ ${this._renderInput(key, schema, !!error2, inputId)}
33811
+ ${error2 ? b2`<div
33812
+ class="error-text"
33813
+ style="margin-left: 8px;"
33814
+ id="${inputId}-error"
33815
+ role="alert"
33816
+ >
33817
+ ${error2}
33818
+ </div>` : ""}
33819
+ </div>
33820
+ </div>
33821
+ `;
33822
+ }
33025
33823
  return b2`
33026
33824
  <div class="form-group">
33027
33825
  <label for=${inputId}>
@@ -34826,6 +35624,9 @@ __decorateClass([
34826
35624
  __decorateClass([
34827
35625
  n4({ type: Object })
34828
35626
  ], InvokeForm.prototype, "sharedValues", 2);
35627
+ __decorateClass([
35628
+ n4({ type: Boolean })
35629
+ ], InvokeForm.prototype, "settingsLayout", 2);
34829
35630
  __decorateClass([
34830
35631
  r5()
34831
35632
  ], InvokeForm.prototype, "_values", 2);
@@ -34853,6 +35654,7 @@ var ActivityLog = class extends i4 {
34853
35654
  constructor() {
34854
35655
  super(...arguments);
34855
35656
  this.items = [];
35657
+ this.fullscreen = false;
34856
35658
  this._filterActive = false;
34857
35659
  this._collapsed = false;
34858
35660
  this._lastFilter = void 0;
@@ -35020,6 +35822,24 @@ ActivityLog.styles = [
35020
35822
  list-style: none;
35021
35823
  margin: 0;
35022
35824
  padding: 0;
35825
+ max-height: 180px;
35826
+ overflow-y: auto;
35827
+ }
35828
+
35829
+ :host([fullscreen]) {
35830
+ display: flex;
35831
+ flex-direction: column;
35832
+ flex: 1;
35833
+ min-height: 0;
35834
+ margin-top: 0;
35835
+ border-top: none;
35836
+ padding-top: 0;
35837
+ }
35838
+
35839
+ :host([fullscreen]) .log-list {
35840
+ max-height: none;
35841
+ flex: 1;
35842
+ min-height: 0;
35023
35843
  }
35024
35844
 
35025
35845
  .log-item {
@@ -35159,6 +35979,9 @@ __decorateClass([
35159
35979
  __decorateClass([
35160
35980
  n4({ type: String })
35161
35981
  ], ActivityLog.prototype, "filter", 2);
35982
+ __decorateClass([
35983
+ n4({ type: Boolean, reflect: true })
35984
+ ], ActivityLog.prototype, "fullscreen", 2);
35162
35985
  __decorateClass([
35163
35986
  r5()
35164
35987
  ], ActivityLog.prototype, "_filterActive", 2);
@@ -39718,33 +40541,32 @@ ${footerText || pageNum ? `<div class="slide-footer"><span>${footerText || ""}</
39718
40541
  }
39719
40542
  }
39720
40543
  _renderSlideFormat(target2, data, format) {
39721
- const win = window;
39722
40544
  const doRender = () => {
39723
- if (win._photonRenderers?.render) {
39724
- win._photonRenderers.render(target2, data, format);
40545
+ if (window._photonRenderers?.render) {
40546
+ window._photonRenderers.render(target2, data, format);
39725
40547
  } else {
39726
40548
  target2.textContent = typeof data === "object" ? JSON.stringify(data, null, 2) : String(data ?? "");
39727
40549
  }
39728
40550
  };
39729
- if (win._photonRenderers) {
40551
+ if (window._photonRenderers) {
39730
40552
  doRender();
39731
- } else if (win._photonRenderersLoading) {
39732
- win._photonRenderersQueue = win._photonRenderersQueue || [];
39733
- win._photonRenderersQueue.push(doRender);
40553
+ } else if (window._photonRenderersLoading) {
40554
+ window._photonRenderersQueue = window._photonRenderersQueue || [];
40555
+ window._photonRenderersQueue.push(doRender);
39734
40556
  } else {
39735
- win._photonRenderersLoading = true;
39736
- win._photonRenderersQueue = [doRender];
40557
+ window._photonRenderersLoading = true;
40558
+ window._photonRenderersQueue = [doRender];
39737
40559
  fetch("/api/photon-renderers.js").then((r7) => r7.text()).then((code) => {
39738
40560
  try {
39739
40561
  (0, eval)(code);
39740
40562
  } catch {
39741
40563
  }
39742
- const queue = win._photonRenderersQueue || [];
39743
- win._photonRenderersQueue = [];
40564
+ const queue = window._photonRenderersQueue || [];
40565
+ window._photonRenderersQueue = [];
39744
40566
  queue.forEach((fn2) => fn2());
39745
40567
  }).catch(() => {
39746
- const queue = win._photonRenderersQueue || [];
39747
- win._photonRenderersQueue = [];
40568
+ const queue = window._photonRenderersQueue || [];
40569
+ window._photonRenderersQueue = [];
39748
40570
  queue.forEach((fn2) => fn2());
39749
40571
  });
39750
40572
  }
@@ -45610,7 +46432,7 @@ var MarketplaceView = class extends i4 {
45610
46432
  try {
45611
46433
  const res = await fetch("/api/marketplace/sources/remove", {
45612
46434
  method: "POST",
45613
- headers: { "Content-Type": "application/json" },
46435
+ headers: { "Content-Type": "application/json", "X-Photon-Request": "1" },
45614
46436
  body: JSON.stringify({ name: name2 }),
45615
46437
  signal: AbortSignal.timeout(1e4)
45616
46438
  });
@@ -45641,6 +46463,7 @@ var MarketplaceView = class extends i4 {
45641
46463
  try {
45642
46464
  const res = await fetch("/api/marketplace/add", {
45643
46465
  method: "POST",
46466
+ headers: { "X-Photon-Request": "1" },
45644
46467
  body: JSON.stringify({ name: item.name }),
45645
46468
  signal: AbortSignal.timeout(3e4)
45646
46469
  // 30s for installation
@@ -45676,6 +46499,7 @@ var MarketplaceView = class extends i4 {
45676
46499
  try {
45677
46500
  const res = await fetch("/api/marketplace/remove", {
45678
46501
  method: "POST",
46502
+ headers: { "X-Photon-Request": "1" },
45679
46503
  body: JSON.stringify({ name: item.name }),
45680
46504
  signal: AbortSignal.timeout(1e4)
45681
46505
  });
@@ -45705,6 +46529,7 @@ var MarketplaceView = class extends i4 {
45705
46529
  try {
45706
46530
  const res = await fetch("/api/marketplace/add", {
45707
46531
  method: "POST",
46532
+ headers: { "X-Photon-Request": "1" },
45708
46533
  body: JSON.stringify({ name: item.name }),
45709
46534
  signal: AbortSignal.timeout(3e4)
45710
46535
  });
@@ -45784,7 +46609,7 @@ var MarketplaceView = class extends i4 {
45784
46609
  try {
45785
46610
  const res = await fetch("/api/marketplace/sources/add", {
45786
46611
  method: "POST",
45787
- headers: { "Content-Type": "application/json" },
46612
+ headers: { "Content-Type": "application/json", "X-Photon-Request": "1" },
45788
46613
  body: JSON.stringify({ source: source3 }),
45789
46614
  signal: AbortSignal.timeout(3e4)
45790
46615
  // 30s for adding repo
@@ -46737,6 +47562,23 @@ var beamTypographyTokens = {
46737
47562
  };
46738
47563
 
46739
47564
  // src/auto-ui/frontend/components/custom-ui-renderer.ts
47565
+ function getBeamThemeTokens(themeMode) {
47566
+ const tokens = getThemeTokens(themeMode);
47567
+ if (themeMode === "dark") {
47568
+ tokens["--color-surface"] = "hsl(220, 15%, 10%)";
47569
+ tokens["--color-surface-container"] = "hsl(220, 15%, 12%)";
47570
+ tokens["--color-surface-container-high"] = "hsl(220, 15%, 14%)";
47571
+ tokens["--color-surface-container-highest"] = "hsl(220, 15%, 16%)";
47572
+ tokens["--bg"] = "hsl(220, 15%, 10%)";
47573
+ } else {
47574
+ tokens["--color-surface"] = "#eae4dd";
47575
+ tokens["--color-surface-container"] = "#f8f5f1";
47576
+ tokens["--color-surface-container-high"] = "#f0ebe5";
47577
+ tokens["--color-surface-container-highest"] = "#e8e2db";
47578
+ tokens["--bg"] = "#eae4dd";
47579
+ }
47580
+ return tokens;
47581
+ }
46740
47582
  var CustomUiRenderer = class extends i4 {
46741
47583
  constructor() {
46742
47584
  super(...arguments);
@@ -46781,7 +47623,7 @@ var CustomUiRenderer = class extends i4 {
46781
47623
  }
46782
47624
  if (changedProperties.has("theme")) {
46783
47625
  if (this._iframeRef?.contentWindow) {
46784
- const themeTokens = getThemeTokens(this.theme);
47626
+ const themeTokens = getBeamThemeTokens(this.theme);
46785
47627
  this._iframeRef.contentWindow.postMessage(
46786
47628
  {
46787
47629
  jsonrpc: "2.0",
@@ -46826,6 +47668,7 @@ var CustomUiRenderer = class extends i4 {
46826
47668
  "sandbox",
46827
47669
  "allow-scripts allow-forms allow-same-origin allow-popups allow-modals"
46828
47670
  );
47671
+ iframe.setAttribute("allowtransparency", "true");
46829
47672
  iframe.addEventListener("load", (e8) => this._handleIframeLoad(e8));
46830
47673
  iframe.src = this._blobUrl;
46831
47674
  container.appendChild(iframe);
@@ -47064,7 +47907,7 @@ var CustomUiRenderer = class extends i4 {
47064
47907
  _handleIframeLoad(e8) {
47065
47908
  const iframe = e8.target;
47066
47909
  this._iframeRef = iframe;
47067
- const themeTokens = getThemeTokens(this.theme);
47910
+ const themeTokens = getBeamThemeTokens(this.theme);
47068
47911
  this._iframeRef?.contentWindow?.postMessage(
47069
47912
  {
47070
47913
  jsonrpc: "2.0",
@@ -47102,16 +47945,20 @@ var CustomUiRenderer = class extends i4 {
47102
47945
  this._contentResizeObserver?.disconnect();
47103
47946
  const body = iframe.contentDocument?.body;
47104
47947
  if (body) {
47105
- this._contentResizeObserver = new ResizeObserver(() => {
47106
- const scrollH = iframe.contentDocument?.body.scrollHeight ?? 0;
47107
- const containerH = this.offsetHeight || 500;
47108
- if (scrollH > containerH) {
47109
- iframe.style.height = scrollH + "px";
47110
- } else {
47111
- iframe.style.height = "";
47112
- }
47113
- });
47114
- this._contentResizeObserver.observe(body);
47948
+ const bodyOverflow = iframe.contentDocument?.defaultView ? getComputedStyle(iframe.contentDocument.body).overflow : "";
47949
+ const isFullHeightApp = bodyOverflow === "hidden";
47950
+ if (!isFullHeightApp) {
47951
+ this._contentResizeObserver = new ResizeObserver(() => {
47952
+ const scrollH = iframe.contentDocument?.body.scrollHeight ?? 0;
47953
+ const containerH = this.offsetHeight || 500;
47954
+ if (scrollH > containerH) {
47955
+ iframe.style.height = scrollH + "px";
47956
+ } else {
47957
+ iframe.style.height = "";
47958
+ }
47959
+ });
47960
+ this._contentResizeObserver.observe(body);
47961
+ }
47115
47962
  }
47116
47963
  }
47117
47964
  disconnectedCallback() {
@@ -47135,7 +47982,7 @@ CustomUiRenderer.styles = [
47135
47982
  width: 100%;
47136
47983
  height: 100%;
47137
47984
  min-height: 500px;
47138
- background: var(--bg-panel, #0d0d0d);
47985
+ background: transparent;
47139
47986
  border-radius: var(--radius-md);
47140
47987
  overflow: visible;
47141
47988
  }
@@ -67115,6 +67962,23 @@ function X_(r7, i7) {
67115
67962
  }
67116
67963
 
67117
67964
  // src/auto-ui/frontend/components/mcp-app-renderer.ts
67965
+ function getBeamThemeTokens2(themeMode) {
67966
+ const tokens = getThemeTokens(themeMode);
67967
+ if (themeMode === "dark") {
67968
+ tokens["--color-surface"] = "hsl(220, 15%, 10%)";
67969
+ tokens["--color-surface-container"] = "hsl(220, 15%, 12%)";
67970
+ tokens["--color-surface-container-high"] = "hsl(220, 15%, 14%)";
67971
+ tokens["--color-surface-container-highest"] = "hsl(220, 15%, 16%)";
67972
+ tokens["--bg"] = "hsl(220, 15%, 10%)";
67973
+ } else {
67974
+ tokens["--color-surface"] = "#eae4dd";
67975
+ tokens["--color-surface-container"] = "#f8f5f1";
67976
+ tokens["--color-surface-container-high"] = "#f0ebe5";
67977
+ tokens["--color-surface-container-highest"] = "#e8e2db";
67978
+ tokens["--bg"] = "#eae4dd";
67979
+ }
67980
+ return tokens;
67981
+ }
67118
67982
  var VALID_STYLE_KEYS = /* @__PURE__ */ new Set([
67119
67983
  // Background colors
67120
67984
  "--color-background-primary",
@@ -67243,14 +68107,14 @@ var McpAppRenderer = class extends i4 {
67243
68107
  willUpdate(changedProperties) {
67244
68108
  if (changedProperties.has("theme")) {
67245
68109
  if (this._bridge) {
67246
- const specTokens = filterSpecVariables(getThemeTokens(this.theme));
68110
+ const specTokens = filterSpecVariables(getBeamThemeTokens2(this.theme));
67247
68111
  this._bridge.setHostContext({
67248
68112
  theme: this.theme,
67249
68113
  styles: { variables: specTokens }
67250
68114
  });
67251
68115
  }
67252
68116
  if (this._iframeRef?.contentWindow) {
67253
- const themeTokens = getThemeTokens(this.theme);
68117
+ const themeTokens = getBeamThemeTokens2(this.theme);
67254
68118
  this._iframeRef.contentWindow.postMessage(
67255
68119
  {
67256
68120
  jsonrpc: "2.0",
@@ -67306,6 +68170,7 @@ var McpAppRenderer = class extends i4 {
67306
68170
  "sandbox",
67307
68171
  "allow-scripts allow-forms allow-same-origin allow-popups allow-modals"
67308
68172
  );
68173
+ iframe.setAttribute("allowtransparency", "true");
67309
68174
  iframe.addEventListener("load", (e8) => this._handleIframeLoad(e8));
67310
68175
  iframe.src = this._blobUrl;
67311
68176
  container.appendChild(iframe);
@@ -67363,7 +68228,7 @@ var McpAppRenderer = class extends i4 {
67363
68228
  const iframe = e8.target;
67364
68229
  this._iframeRef = iframe;
67365
68230
  if (!iframe.contentWindow) return;
67366
- const themeTokens = getThemeTokens(this.theme);
68231
+ const themeTokens = getBeamThemeTokens2(this.theme);
67367
68232
  iframe.contentWindow.postMessage(
67368
68233
  {
67369
68234
  jsonrpc: "2.0",
@@ -67407,7 +68272,7 @@ var McpAppRenderer = class extends i4 {
67407
68272
  const msg = event.data;
67408
68273
  if (!msg || typeof msg !== "object") return;
67409
68274
  if (msg.jsonrpc === "2.0" && msg.method === "ui/initialize" && msg.id != null) {
67410
- const themeTokens2 = getThemeTokens(this.theme);
68275
+ const themeTokens2 = getBeamThemeTokens2(this.theme);
67411
68276
  iframe.contentWindow?.postMessage(
67412
68277
  {
67413
68278
  jsonrpc: "2.0",
@@ -67476,7 +68341,7 @@ var McpAppRenderer = class extends i4 {
67476
68341
  void asyncMessageHandler(event);
67477
68342
  };
67478
68343
  window.addEventListener("message", this._messageHandler);
67479
- const specTokens = filterSpecVariables(getThemeTokens(this.theme));
68344
+ const specTokens = filterSpecVariables(getBeamThemeTokens2(this.theme));
67480
68345
  this._bridge = new W_(
67481
68346
  null,
67482
68347
  { name: "Photon Beam", version: "1.0.0" },
@@ -67615,7 +68480,7 @@ McpAppRenderer.styles = [
67615
68480
  width: 100%;
67616
68481
  height: 100%;
67617
68482
  min-height: 500px;
67618
- background: var(--bg-panel, #0d0d0d);
68483
+ background: transparent;
67619
68484
  border-radius: var(--radius-md);
67620
68485
  overflow: visible;
67621
68486
  }
@@ -99608,15 +100473,21 @@ var ForkDialog = class extends i4 {
99608
100473
  super(...arguments);
99609
100474
  this.photonName = "";
99610
100475
  this.originRepo = "";
100476
+ this.requireNewName = false;
100477
+ this.suggestedName = "";
99611
100478
  this.targets = [];
99612
100479
  this._selectedTarget = "local";
99613
100480
  this._newRepoName = "";
100481
+ this._newPhotonName = "";
99614
100482
  }
99615
100483
  render() {
99616
100484
  return b2`
99617
100485
  <div class="modal-content" @click=${(e8) => e8.stopPropagation()}>
99618
100486
  <h3>Fork ${this.photonName}</h3>
99619
100487
  ${this.originRepo ? b2`<div class="origin-info">From ${this.originRepo}</div>` : ""}
100488
+ <div class="origin-info">
100489
+ ${this.requireNewName ? "This photon is already local, so the fork needs a new local name." : "Marketplace forks keep the same local name unless you choose another one."}
100490
+ </div>
99620
100491
 
99621
100492
  <div class="target-list">
99622
100493
  ${this.targets.map(
@@ -99668,16 +100539,26 @@ var ForkDialog = class extends i4 {
99668
100539
  <div class="target-radio"></div>
99669
100540
  <div class="target-info">
99670
100541
  <div class="target-name">Local only</div>
99671
- <div class="target-repo">Remove marketplace tracking, keep file as-is</div>
100542
+ <div class="target-repo">Create or keep a local editable copy</div>
99672
100543
  </div>
99673
100544
  </div>
99674
100545
  </div>
99675
100546
 
100547
+ <input
100548
+ class="create-repo-input"
100549
+ type="text"
100550
+ placeholder=${this.suggestedName || (this.requireNewName ? "new-local-name" : "Optional local name")}
100551
+ .value=${this._newPhotonName}
100552
+ @input=${(e8) => {
100553
+ this._newPhotonName = e8.target.value;
100554
+ }}
100555
+ />
100556
+
99676
100557
  <div class="actions">
99677
100558
  <button class="btn" @click=${() => this._cancel()}>Cancel</button>
99678
100559
  <button
99679
100560
  class="btn btn-primary"
99680
- ?disabled=${this._selectedTarget === "create" && !this._newRepoName.trim()}
100561
+ ?disabled=${this._selectedTarget === "create" && !this._newRepoName.trim() || this.requireNewName && !this._newPhotonName.trim()}
99681
100562
  @click=${() => this._confirm()}
99682
100563
  >
99683
100564
  Fork
@@ -99695,7 +100576,7 @@ var ForkDialog = class extends i4 {
99695
100576
  }
99696
100577
  this.dispatchEvent(
99697
100578
  new CustomEvent("fork-confirm", {
99698
- detail: { target: target2 },
100579
+ detail: { target: target2, newName: this._newPhotonName.trim() || void 0 },
99699
100580
  bubbles: true,
99700
100581
  composed: true
99701
100582
  })
@@ -99879,6 +100760,12 @@ __decorateClass([
99879
100760
  __decorateClass([
99880
100761
  n4()
99881
100762
  ], ForkDialog.prototype, "originRepo", 2);
100763
+ __decorateClass([
100764
+ n4({ type: Boolean })
100765
+ ], ForkDialog.prototype, "requireNewName", 2);
100766
+ __decorateClass([
100767
+ n4()
100768
+ ], ForkDialog.prototype, "suggestedName", 2);
99882
100769
  __decorateClass([
99883
100770
  n4({ type: Array })
99884
100771
  ], ForkDialog.prototype, "targets", 2);
@@ -99888,6 +100775,9 @@ __decorateClass([
99888
100775
  __decorateClass([
99889
100776
  r5()
99890
100777
  ], ForkDialog.prototype, "_newRepoName", 2);
100778
+ __decorateClass([
100779
+ r5()
100780
+ ], ForkDialog.prototype, "_newPhotonName", 2);
99891
100781
  ForkDialog = __decorateClass([
99892
100782
  t4("fork-dialog")
99893
100783
  ], ForkDialog);
@@ -99898,6 +100788,7 @@ var AppLayout = class extends i4 {
99898
100788
  super(...arguments);
99899
100789
  this.photonName = "";
99900
100790
  this.photonIcon = "";
100791
+ this.hideBelow = false;
99901
100792
  this._poppedOut = false;
99902
100793
  this._handleKeydown = (e8) => {
99903
100794
  if (e8.key === "Escape" && this._poppedOut) {
@@ -99955,6 +100846,34 @@ AppLayout.styles = [
99955
100846
  display: block;
99956
100847
  }
99957
100848
 
100849
+ :host([hide-below]) .scroll-divider,
100850
+ :host([hide-below]) .below-fold {
100851
+ display: none;
100852
+ }
100853
+
100854
+ /* App tab mode: fill the available flex height instead of using min-height */
100855
+ :host([hide-below]) {
100856
+ flex: 1;
100857
+ min-height: 0;
100858
+ height: 100%;
100859
+ }
100860
+
100861
+ :host([hide-below]) .app-viewport {
100862
+ min-height: unset;
100863
+ height: 100%;
100864
+ display: flex;
100865
+ flex-direction: column;
100866
+ /* Remove rounded corners and clipping — we fill the full viewport */
100867
+ border-radius: 0;
100868
+ overflow: visible;
100869
+ }
100870
+
100871
+ :host([hide-below]) .app-content {
100872
+ overflow: hidden;
100873
+ flex: 1;
100874
+ min-height: 0;
100875
+ }
100876
+
99958
100877
  .app-viewport {
99959
100878
  min-height: calc(100vh - 140px);
99960
100879
  border-radius: var(--radius-md);
@@ -100064,6 +100983,9 @@ __decorateClass([
100064
100983
  __decorateClass([
100065
100984
  n4({ type: String })
100066
100985
  ], AppLayout.prototype, "photonIcon", 2);
100986
+ __decorateClass([
100987
+ n4({ type: Boolean, reflect: true, attribute: "hide-below" })
100988
+ ], AppLayout.prototype, "hideBelow", 2);
100067
100989
  __decorateClass([
100068
100990
  r5()
100069
100991
  ], AppLayout.prototype, "_poppedOut", 2);