@trops/dash-core 0.1.295 → 0.1.297

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.
@@ -30050,7 +30050,7 @@ async function deleteRegistryPackage(scope, name) {
30050
30050
  }
30051
30051
  }
30052
30052
 
30053
- var registryAuthController$1 = {
30053
+ var registryAuthController$2 = {
30054
30054
  initiateDeviceFlow: initiateDeviceFlow$1,
30055
30055
  pollForToken: pollForToken$1,
30056
30056
  getStoredToken: getStoredToken$3,
@@ -31010,7 +31010,7 @@ var schedulerController_1 = schedulerController$2;
31010
31010
  const { dynamicWidgetLoader } = dynamicWidgetLoaderExports;
31011
31011
  const { compileWidget, findWidgetsDir } = widgetCompiler$1;
31012
31012
  const { toPackageId, parsePackageId } = packageId;
31013
- const { getStoredToken } = registryAuthController$1;
31013
+ const { getStoredToken } = registryAuthController$2;
31014
31014
 
31015
31015
  let WIDGETS_CACHE_DIR = null;
31016
31016
  let REGISTRY_CONFIG_FILE = null;
@@ -32207,7 +32207,7 @@ var widgetRegistryExports = widgetRegistry$1.exports;
32207
32207
 
32208
32208
  const fs$1 = require$$0$3;
32209
32209
  const path$4 = require$$1$2;
32210
- const { getStoredToken: getStoredToken$2 } = registryAuthController$1;
32210
+ const { getStoredToken: getStoredToken$2 } = registryAuthController$2;
32211
32211
 
32212
32212
  const REGISTRY_BASE_URL =
32213
32213
  process.env.DASH_REGISTRY_API_URL ||
@@ -32315,7 +32315,7 @@ const {
32315
32315
  getRegistryProfile: getRegistryProfile$1,
32316
32316
  getStoredToken: getStoredToken$1,
32317
32317
  clearToken: clearToken$1,
32318
- } = registryAuthController$1;
32318
+ } = registryAuthController$2;
32319
32319
 
32320
32320
  /**
32321
32321
  * Sanitize a name for use as a filename (lowercase, hyphens only).
@@ -32889,7 +32889,7 @@ const {
32889
32889
  applyEventWiringToLayout,
32890
32890
  } = dashboardConfigUtils$1;
32891
32891
  const { searchRegistry, getPackage } = registryController$3;
32892
- const { getStoredToken, clearToken } = registryAuthController$1;
32892
+ const { getStoredToken, clearToken } = registryAuthController$2;
32893
32893
  const themeController$3 = themeController_1;
32894
32894
 
32895
32895
  const configFilename = "workspaces.json";
@@ -34089,7 +34089,7 @@ async function prepareDashboardForPublish$1(
34089
34089
  let registryUsername = options.githubUser || "";
34090
34090
  if (!registryUsername) {
34091
34091
  try {
34092
- const { getRegistryProfile } = registryAuthController$1;
34092
+ const { getRegistryProfile } = registryAuthController$2;
34093
34093
  const profile = await getRegistryProfile();
34094
34094
  registryUsername = profile?.username || options.authorId || "";
34095
34095
  } catch {
@@ -34139,7 +34139,7 @@ async function prepareDashboardForPublish$1(
34139
34139
  // 11. Attempt to publish to registry if authenticated
34140
34140
  let registrySubmission = null;
34141
34141
  try {
34142
- const { getAuthStatus } = registryAuthController$1;
34142
+ const { getAuthStatus } = registryAuthController$2;
34143
34143
  const { publishToRegistry } = registryApiController$2;
34144
34144
  const authStatus = getAuthStatus();
34145
34145
 
@@ -68015,7 +68015,7 @@ const {
68015
68015
  getRegistryPackages,
68016
68016
  updateRegistryPackage,
68017
68017
  clearToken: clearRegistryToken,
68018
- } = registryAuthController$1;
68018
+ } = registryAuthController$2;
68019
68019
  const {
68020
68020
  publishToRegistry,
68021
68021
  getRegistryUrl,
@@ -70367,7 +70367,7 @@ const widgetTools$1 = [
70367
70367
  {
70368
70368
  name: "list_widgets",
70369
70369
  description:
70370
- "List all available widgets from the registry. Returns scoped component names (e.g. 'trops.gong.GongCallSearch') that can be passed directly to add_widget. Also includes description, provider requirements, and package info.",
70370
+ "List all available widgets from the registry. Returns scoped component names (e.g. 'trops.gong.GongCallSearch') that can be passed directly to add_widget. Each widget includes an 'installed' boolean — if true, use add_widget directly; if false, call install_widget first. Also includes description, provider requirements, and package info.",
70371
70371
  inputSchema: {
70372
70372
  type: "object",
70373
70373
  properties: {},
@@ -70377,7 +70377,7 @@ const widgetTools$1 = [
70377
70377
  {
70378
70378
  name: "search_widgets",
70379
70379
  description:
70380
- "Search the widget registry by keyword. Returns matching widgets with scoped names (e.g. 'trops.slack.SlackChannelFeed') that can be passed directly to add_widget. Also includes description and provider info.",
70380
+ "Search the widget registry by keyword. Returns matching widgets with scoped names (e.g. 'trops.slack.SlackChannelFeed') that can be passed directly to add_widget. Each widget includes an 'installed' boolean — if true, use add_widget directly; if false, call install_widget first. Also includes description and provider info.",
70381
70381
  inputSchema: {
70382
70382
  type: "object",
70383
70383
  properties: {
@@ -70390,6 +70390,22 @@ const widgetTools$1 = [
70390
70390
  required: ["query"],
70391
70391
  },
70392
70392
  },
70393
+ {
70394
+ name: "install_widget",
70395
+ description:
70396
+ "Install a widget package from the Dash registry. Requires registry authentication — the user must be signed in via Settings > Account in the Dash app. Use search_widgets first to find available packages, then install by package name (e.g., 'slack', 'gong', 'chat'). After installation, use add_widget to place it on a dashboard.",
70397
+ inputSchema: {
70398
+ type: "object",
70399
+ properties: {
70400
+ packageName: {
70401
+ type: "string",
70402
+ description:
70403
+ "Package name from the registry (e.g., 'slack', 'gong', 'chat'). Use the 'package' field from search_widgets results.",
70404
+ },
70405
+ },
70406
+ required: ["packageName"],
70407
+ },
70408
+ },
70393
70409
  ];
70394
70410
 
70395
70411
  const themeTools$1 = [
@@ -71099,6 +71115,8 @@ async function handleGetAppStats$1() {
71099
71115
  // --- Widget Tool Handlers ---
71100
71116
 
71101
71117
  const registryController$1 = registryController$3;
71118
+ const registryAuthController$1 = registryAuthController$2;
71119
+ const { getWidgetRegistry } = widgetRegistryExports;
71102
71120
 
71103
71121
  /**
71104
71122
  * Helper: find a workspace by ID or return the first (active) one.
@@ -71619,6 +71637,41 @@ async function handleConfigureWidget$1({ dashboardId, widgetId, config }) {
71619
71637
  };
71620
71638
  }
71621
71639
 
71640
+ /**
71641
+ * Build a Set of installed package identifiers for quick lookup.
71642
+ * Includes both scoped ("@trops/slack") and bare ("slack") forms.
71643
+ */
71644
+ function getInstalledPackageNames() {
71645
+ const installed = new Set();
71646
+ try {
71647
+ const registry = getWidgetRegistry();
71648
+ const widgets = registry.getWidgets();
71649
+ for (const w of widgets) {
71650
+ const name = w.name || w.packageId || "";
71651
+ installed.add(name.toLowerCase());
71652
+ // Also add bare name for scoped packages ("@trops/slack" → "slack")
71653
+ if (name.includes("/")) {
71654
+ installed.add(name.split("/").pop().toLowerCase());
71655
+ }
71656
+ }
71657
+ } catch {
71658
+ // Widget registry may not be initialized (e.g. in tests)
71659
+ }
71660
+ return installed;
71661
+ }
71662
+
71663
+ /**
71664
+ * Check if a registry package is locally installed.
71665
+ */
71666
+ function isPackageInstalled(pkg, installedNames) {
71667
+ const candidates = [
71668
+ pkg.name,
71669
+ pkg.scope ? `@${pkg.scope}/${pkg.name}` : null,
71670
+ pkg.scope ? `${pkg.scope}/${pkg.name}` : null,
71671
+ ].filter(Boolean);
71672
+ return candidates.some((c) => installedNames.has(c.toLowerCase()));
71673
+ }
71674
+
71622
71675
  /**
71623
71676
  * list_widgets — List available widgets from the registry.
71624
71677
  */
@@ -71626,12 +71679,15 @@ async function handleListWidgets$1() {
71626
71679
  try {
71627
71680
  const index = await registryController$1.fetchRegistryIndex();
71628
71681
  const packages = index.packages || [];
71682
+ const installedNames = getInstalledPackageNames();
71629
71683
 
71630
71684
  const widgets = [];
71631
71685
  for (const pkg of packages) {
71632
71686
  // Skip non-widget packages
71633
71687
  if (pkg.type && pkg.type !== "widget") continue;
71634
71688
 
71689
+ const installed = isPackageInstalled(pkg, installedNames);
71690
+
71635
71691
  for (const w of pkg.widgets || []) {
71636
71692
  const shortName = w.name || pkg.name;
71637
71693
  const scopedName =
@@ -71645,6 +71701,7 @@ async function handleListWidgets$1() {
71645
71701
  icon: w.icon || pkg.icon || null,
71646
71702
  package: pkg.name,
71647
71703
  scope: pkg.scope || null,
71704
+ installed,
71648
71705
  providers: (w.providers || pkg.providers || []).map((p) => ({
71649
71706
  type: p.type,
71650
71707
  providerClass: p.providerClass || "api",
@@ -71666,6 +71723,7 @@ async function handleListWidgets$1() {
71666
71723
  icon: pkg.icon || null,
71667
71724
  package: pkg.name,
71668
71725
  scope: pkg.scope || null,
71726
+ installed,
71669
71727
  providers: (pkg.providers || []).map((p) => ({
71670
71728
  type: p.type,
71671
71729
  providerClass: p.providerClass || "api",
@@ -71719,11 +71777,14 @@ async function handleSearchWidgets$1({ query }) {
71719
71777
  try {
71720
71778
  const result = await registryController$1.searchRegistry(query.trim());
71721
71779
  const packages = result.packages || [];
71780
+ const installedNames = getInstalledPackageNames();
71722
71781
 
71723
71782
  const widgets = [];
71724
71783
  for (const pkg of packages) {
71725
71784
  if (pkg.type && pkg.type !== "widget") continue;
71726
71785
 
71786
+ const installed = isPackageInstalled(pkg, installedNames);
71787
+
71727
71788
  for (const w of pkg.widgets || []) {
71728
71789
  const shortName = w.name || pkg.name;
71729
71790
  const scopedName =
@@ -71737,6 +71798,7 @@ async function handleSearchWidgets$1({ query }) {
71737
71798
  icon: w.icon || pkg.icon || null,
71738
71799
  package: pkg.name,
71739
71800
  scope: pkg.scope || null,
71801
+ installed,
71740
71802
  providers: (w.providers || pkg.providers || []).map((p) => ({
71741
71803
  type: p.type,
71742
71804
  providerClass: p.providerClass || "api",
@@ -71757,6 +71819,7 @@ async function handleSearchWidgets$1({ query }) {
71757
71819
  icon: pkg.icon || null,
71758
71820
  package: pkg.name,
71759
71821
  scope: pkg.scope || null,
71822
+ installed,
71760
71823
  providers: (pkg.providers || []).map((p) => ({
71761
71824
  type: p.type,
71762
71825
  providerClass: p.providerClass || "api",
@@ -71793,6 +71856,155 @@ async function handleSearchWidgets$1({ query }) {
71793
71856
  }
71794
71857
  }
71795
71858
 
71859
+ /**
71860
+ * install_widget — Install a widget package from the Dash registry.
71861
+ * Requires the user to be authenticated via Settings > Account.
71862
+ */
71863
+ async function handleInstallWidget$1({ packageName }) {
71864
+ if (!packageName || typeof packageName !== "string" || !packageName.trim()) {
71865
+ return {
71866
+ content: [
71867
+ {
71868
+ type: "text",
71869
+ text: JSON.stringify({
71870
+ error: "packageName is required and must be a non-empty string",
71871
+ }),
71872
+ },
71873
+ ],
71874
+ isError: true,
71875
+ };
71876
+ }
71877
+
71878
+ // Check authentication
71879
+ const auth = registryAuthController$1.getStoredToken();
71880
+ if (!auth) {
71881
+ return {
71882
+ content: [
71883
+ {
71884
+ type: "text",
71885
+ text: JSON.stringify({
71886
+ error:
71887
+ "Not authenticated with the Dash registry. Please sign in via Settings > Account in the Dash app first.",
71888
+ authRequired: true,
71889
+ }),
71890
+ },
71891
+ ],
71892
+ isError: true,
71893
+ };
71894
+ }
71895
+
71896
+ try {
71897
+ // Look up the package in the registry
71898
+ const pkg = await registryController$1.getPackage(packageName.trim());
71899
+ if (!pkg) {
71900
+ return {
71901
+ content: [
71902
+ {
71903
+ type: "text",
71904
+ text: JSON.stringify({
71905
+ error: `Package "${packageName}" not found in the registry. Use search_widgets to find available packages.`,
71906
+ }),
71907
+ },
71908
+ ],
71909
+ isError: true,
71910
+ };
71911
+ }
71912
+
71913
+ if (!pkg.downloadUrl) {
71914
+ return {
71915
+ content: [
71916
+ {
71917
+ type: "text",
71918
+ text: JSON.stringify({
71919
+ error: `Package "${packageName}" has no download URL in the registry.`,
71920
+ }),
71921
+ },
71922
+ ],
71923
+ isError: true,
71924
+ };
71925
+ }
71926
+
71927
+ // Download and install
71928
+ const registry = getWidgetRegistry();
71929
+ const config = await registry.downloadWidget(pkg.name, pkg.downloadUrl);
71930
+
71931
+ // Notify all renderer windows
71932
+ const { win } = requireContext$1();
71933
+ const { BrowserWindow } = require("electron");
71934
+ BrowserWindow.getAllWindows().forEach((w) => {
71935
+ w.webContents.send("widget:installed", {
71936
+ widgetName: pkg.name,
71937
+ config,
71938
+ });
71939
+ });
71940
+
71941
+ // Build the list of installed widget names for the response
71942
+ const widgetNames = (pkg.widgets || []).map((w) => {
71943
+ const scopedName =
71944
+ pkg.scope && pkg.name && w.name
71945
+ ? `${pkg.scope}.${pkg.name}.${w.name}`
71946
+ : w.name || pkg.name;
71947
+ return {
71948
+ name: scopedName,
71949
+ displayName: w.displayName || w.name,
71950
+ };
71951
+ });
71952
+
71953
+ return {
71954
+ content: [
71955
+ {
71956
+ type: "text",
71957
+ text: JSON.stringify(
71958
+ {
71959
+ success: true,
71960
+ package: pkg.name,
71961
+ scope: pkg.scope || null,
71962
+ version: pkg.version || null,
71963
+ widgets: widgetNames,
71964
+ message: `Successfully installed "${pkg.displayName || pkg.name}". Use add_widget with the widget names above to add them to a dashboard.`,
71965
+ },
71966
+ null,
71967
+ 2,
71968
+ ),
71969
+ },
71970
+ ],
71971
+ };
71972
+ } catch (err) {
71973
+ // Handle auth expiration
71974
+ if (
71975
+ err.message &&
71976
+ (err.message.includes("401") || err.message.includes("Unauthorized"))
71977
+ ) {
71978
+ registryAuthController$1.clearToken();
71979
+ return {
71980
+ content: [
71981
+ {
71982
+ type: "text",
71983
+ text: JSON.stringify({
71984
+ error:
71985
+ "Authentication expired. Please sign in again via Settings > Account in the Dash app.",
71986
+ authRequired: true,
71987
+ }),
71988
+ },
71989
+ ],
71990
+ isError: true,
71991
+ };
71992
+ }
71993
+
71994
+ return {
71995
+ content: [
71996
+ {
71997
+ type: "text",
71998
+ text: JSON.stringify({
71999
+ error: `Failed to install widget package: ${err.message}`,
72000
+ }),
72001
+ },
72002
+ ],
72003
+ isError: true,
72004
+ };
72005
+ }
72006
+ }
72007
+
71796
72008
  // --- Theme Tool Handlers ---
71797
72009
 
71798
72010
  const settingsController$2 = settingsController_1;
@@ -73177,6 +73389,7 @@ var toolHandlers = {
73177
73389
  handleConfigureWidget: handleConfigureWidget$1,
73178
73390
  handleListWidgets: handleListWidgets$1,
73179
73391
  handleSearchWidgets: handleSearchWidgets$1,
73392
+ handleInstallWidget: handleInstallWidget$1,
73180
73393
  handleListThemes: handleListThemes$1,
73181
73394
  handleGetTheme: handleGetTheme$1,
73182
73395
  handleCreateTheme: handleCreateTheme$1,
@@ -73261,6 +73474,7 @@ const {
73261
73474
  handleConfigureWidget,
73262
73475
  handleListWidgets,
73263
73476
  handleSearchWidgets,
73477
+ handleInstallWidget,
73264
73478
  } = toolHandlers;
73265
73479
 
73266
73480
  // Map tool names to handler functions
@@ -73270,6 +73484,7 @@ const handlerMap$6 = {
73270
73484
  configure_widget: handleConfigureWidget,
73271
73485
  list_widgets: handleListWidgets,
73272
73486
  search_widgets: handleSearchWidgets,
73487
+ install_widget: handleInstallWidget,
73273
73488
  };
73274
73489
 
73275
73490
  /**
@@ -74371,7 +74586,7 @@ const pluginController = pluginController_1;
74371
74586
  const llmController = llmController_1;
74372
74587
  const cliController = cliController_1;
74373
74588
  const dashboardConfigController = dashboardConfigController$1;
74374
- const registryAuthController = registryAuthController$1;
74589
+ const registryAuthController = registryAuthController$2;
74375
74590
  const registryApiController = registryApiController$2;
74376
74591
  const notificationController = notificationController_1;
74377
74592
  const schedulerController = schedulerController_1;