@trops/dash-core 0.1.640 → 0.1.641

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.
package/dist/index.js CHANGED
@@ -47458,45 +47458,85 @@ function widgetSubscription(workspace, widget, event) {
47458
47458
  * otherwise they show as typed.
47459
47459
  */
47460
47460
  function describeSubscription(sub, catalog) {
47461
+ var botCatalog = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
47461
47462
  var eventType = sub && sub.eventType;
47462
- var _iterator2 = _createForOfIteratorHelper$m(catalog || []),
47463
- _step2;
47463
+ // Bot subscriptions resolve against the bot catalog; `kind` lets the form
47464
+ // say "bot missing" instead of "widget missing".
47465
+ if (sub && sub.source && sub.source.kind === "bot") {
47466
+ var _iterator2 = _createForOfIteratorHelper$m(botCatalog || []),
47467
+ _step2;
47468
+ try {
47469
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
47470
+ var b = _step2.value;
47471
+ var _iterator3 = _createForOfIteratorHelper$m(b.events),
47472
+ _step3;
47473
+ try {
47474
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
47475
+ var ev = _step3.value;
47476
+ var s = botSubscription(b, ev);
47477
+ if (s.eventType === eventType) {
47478
+ return {
47479
+ label: s.label,
47480
+ missing: false,
47481
+ kind: "bot"
47482
+ };
47483
+ }
47484
+ }
47485
+ } catch (err) {
47486
+ _iterator3.e(err);
47487
+ } finally {
47488
+ _iterator3.f();
47489
+ }
47490
+ }
47491
+ } catch (err) {
47492
+ _iterator2.e(err);
47493
+ } finally {
47494
+ _iterator2.f();
47495
+ }
47496
+ return {
47497
+ label: sub.label || eventType,
47498
+ missing: true,
47499
+ kind: "bot"
47500
+ };
47501
+ }
47502
+ var _iterator4 = _createForOfIteratorHelper$m(catalog || []),
47503
+ _step4;
47464
47504
  try {
47465
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
47466
- var ws = _step2.value;
47467
- var _iterator3 = _createForOfIteratorHelper$m(ws.widgets),
47468
- _step3;
47505
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
47506
+ var ws = _step4.value;
47507
+ var _iterator5 = _createForOfIteratorHelper$m(ws.widgets),
47508
+ _step5;
47469
47509
  try {
47470
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
47471
- var w = _step3.value;
47472
- var _iterator4 = _createForOfIteratorHelper$m(w.events),
47473
- _step4;
47510
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
47511
+ var w = _step5.value;
47512
+ var _iterator6 = _createForOfIteratorHelper$m(w.events),
47513
+ _step6;
47474
47514
  try {
47475
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
47476
- var ev = _step4.value;
47477
- if (formatEventString(w.ref, w.instanceId, ev) === eventType) {
47515
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
47516
+ var _ev = _step6.value;
47517
+ if (formatEventString(w.ref, w.instanceId, _ev) === eventType) {
47478
47518
  return {
47479
- label: widgetSubscription(ws, w, ev).label,
47519
+ label: widgetSubscription(ws, w, _ev).label,
47480
47520
  missing: false
47481
47521
  };
47482
47522
  }
47483
47523
  }
47484
47524
  } catch (err) {
47485
- _iterator4.e(err);
47525
+ _iterator6.e(err);
47486
47526
  } finally {
47487
- _iterator4.f();
47527
+ _iterator6.f();
47488
47528
  }
47489
47529
  }
47490
47530
  } catch (err) {
47491
- _iterator3.e(err);
47531
+ _iterator5.e(err);
47492
47532
  } finally {
47493
- _iterator3.f();
47533
+ _iterator5.f();
47494
47534
  }
47495
47535
  }
47496
47536
  } catch (err) {
47497
- _iterator2.e(err);
47537
+ _iterator4.e(err);
47498
47538
  } finally {
47499
- _iterator2.f();
47539
+ _iterator4.f();
47500
47540
  }
47501
47541
  if (sub && sub.source) {
47502
47542
  return {
@@ -47510,8 +47550,122 @@ function describeSubscription(sub, catalog) {
47510
47550
  };
47511
47551
  }
47512
47552
 
47553
+ /**
47554
+ * Events other bots publish (bot:<ref>[<botId>].<event>, PRD US-010), for the
47555
+ * "Another bot" side of the picker. Derived from each bot's settings — never
47556
+ * hand-declared: Completed, Failed, and one `tool.<providerType>.<tool>` per
47557
+ * tool the bot may use (the provider's tools, narrowed by the bot's
47558
+ * selection). Providers with no known type or tool list are skipped.
47559
+ *
47560
+ * @param {Array<object>} bots
47561
+ * @param {Array<{name, type, tools}>} toolSources bots.listToolSources()
47562
+ * @param {string} [excludeBotId] the bot being edited — can't trigger itself
47563
+ */
47564
+ function buildBotEventCatalog(bots, toolSources) {
47565
+ var excludeBotId = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
47566
+ if (!Array.isArray(bots)) return [];
47567
+ var sources = Array.isArray(toolSources) ? toolSources : [];
47568
+ var out = [];
47569
+ var _iterator7 = _createForOfIteratorHelper$m(bots),
47570
+ _step7;
47571
+ try {
47572
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
47573
+ var bot = _step7.value;
47574
+ if (!bot || !bot.id || !bot.ref || bot.id === excludeBotId) continue;
47575
+ var events = [{
47576
+ event: "completed",
47577
+ label: "Completed"
47578
+ }, {
47579
+ event: "failed",
47580
+ label: "Failed"
47581
+ }];
47582
+ var _iterator8 = _createForOfIteratorHelper$m(bot.mcpServers || []),
47583
+ _step8;
47584
+ try {
47585
+ var _loop = function _loop() {
47586
+ var provider = _step8.value;
47587
+ var src = sources.find(function (s) {
47588
+ return s && s.name === provider;
47589
+ });
47590
+ if (!src || !src.type || !Array.isArray(src.tools)) return 1; // continue
47591
+ var sel = bot.toolSelections && bot.toolSelections[provider];
47592
+ var tools = Array.isArray(sel) ? src.tools.filter(function (t) {
47593
+ return sel.includes(t);
47594
+ }) : src.tools;
47595
+ var _iterator9 = _createForOfIteratorHelper$m(tools),
47596
+ _step9;
47597
+ try {
47598
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
47599
+ var tool = _step9.value;
47600
+ events.push({
47601
+ event: "tool.".concat(src.type, ".").concat(tool),
47602
+ label: "".concat(provider, " \u203A ").concat(tool)
47603
+ });
47604
+ }
47605
+ } catch (err) {
47606
+ _iterator9.e(err);
47607
+ } finally {
47608
+ _iterator9.f();
47609
+ }
47610
+ };
47611
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
47612
+ if (_loop()) continue;
47613
+ }
47614
+ } catch (err) {
47615
+ _iterator8.e(err);
47616
+ } finally {
47617
+ _iterator8.f();
47618
+ }
47619
+ out.push({
47620
+ botId: bot.id,
47621
+ ref: bot.ref,
47622
+ name: bot.name || bot.id,
47623
+ events: events
47624
+ });
47625
+ }
47626
+ } catch (err) {
47627
+ _iterator7.e(err);
47628
+ } finally {
47629
+ _iterator7.f();
47630
+ }
47631
+ return out;
47632
+ }
47633
+
47634
+ /** A subscription to one bot event, picked from the bot catalog. */
47635
+ function botSubscription(botEntry, ev) {
47636
+ return {
47637
+ eventType: "bot:".concat(botEntry.ref, "[").concat(botEntry.botId, "].").concat(ev.event),
47638
+ source: {
47639
+ kind: "bot",
47640
+ ref: botEntry.ref,
47641
+ instanceId: botEntry.botId,
47642
+ event: ev.event
47643
+ },
47644
+ label: "".concat(botEntry.name, " \u203A ").concat(ev.label)
47645
+ };
47646
+ }
47647
+
47513
47648
  function ownKeys$t(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
47514
47649
  function _objectSpread$t(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$t(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$t(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
47650
+ var EVENT_FROM_OPTIONS = [{
47651
+ value: "widget",
47652
+ label: "A dashboard widget"
47653
+ }, {
47654
+ value: "bot",
47655
+ label: "Another bot"
47656
+ }];
47657
+
47658
+ /**
47659
+ * BotDetail — create/edit form for a Bot Factory bot (Settings → Bots).
47660
+ *
47661
+ * Built for a non-technical user: Providers (the user's Dash MCP providers —
47662
+ * what the bot can use), the AI model, and the schedule are all
47663
+ * pick-from-a-list, never free text. "Provider" always means a Dash provider;
47664
+ * the LLM choice is labelled "Model source". The raw cron lives behind an "Advanced"
47665
+ * toggle for power users. All inputs are @trops/dash-react primitives.
47666
+ */
47667
+
47668
+ // Friendly, Title-case provider labels for the dropdown.
47515
47669
  var PROVIDER_LABELS = {
47516
47670
  anthropic: "Anthropic",
47517
47671
  openai: "OpenAI",
@@ -47617,6 +47771,8 @@ var BotDetail = function BotDetail(_ref) {
47617
47771
  workspaces = _ref$workspaces === void 0 ? EMPTY_LIST : _ref$workspaces,
47618
47772
  _ref$getWidgetConfig = _ref.getWidgetConfig,
47619
47773
  getWidgetConfig = _ref$getWidgetConfig === void 0 ? null : _ref$getWidgetConfig,
47774
+ _ref$bots = _ref.bots,
47775
+ bots = _ref$bots === void 0 ? EMPTY_LIST : _ref$bots,
47620
47776
  onSave = _ref.onSave,
47621
47777
  onCancel = _ref.onCancel,
47622
47778
  onDelete = _ref.onDelete;
@@ -47772,26 +47928,34 @@ var BotDetail = function BotDetail(_ref) {
47772
47928
  var eventCatalog = React.useMemo(function () {
47773
47929
  return buildWidgetEventCatalog(workspaces, getWidgetConfig);
47774
47930
  }, [workspaces, getWidgetConfig]);
47775
- var _useState39 = React.useState(""),
47931
+ var _useState39 = React.useState("widget"),
47776
47932
  _useState40 = _slicedToArray(_useState39, 2),
47777
- pickWorkspace = _useState40[0],
47778
- setPickWorkspace = _useState40[1];
47933
+ pickFrom = _useState40[0],
47934
+ setPickFrom = _useState40[1];
47779
47935
  var _useState41 = React.useState(""),
47780
47936
  _useState42 = _slicedToArray(_useState41, 2),
47781
- pickWidget = _useState42[0],
47782
- setPickWidget = _useState42[1];
47937
+ pickWorkspace = _useState42[0],
47938
+ setPickWorkspace = _useState42[1];
47783
47939
  var _useState43 = React.useState(""),
47784
47940
  _useState44 = _slicedToArray(_useState43, 2),
47785
- pickEvent = _useState44[0],
47786
- setPickEvent = _useState44[1];
47787
- var _useState45 = React.useState(false),
47941
+ pickWidget = _useState44[0],
47942
+ setPickWidget = _useState44[1];
47943
+ var _useState45 = React.useState(""),
47788
47944
  _useState46 = _slicedToArray(_useState45, 2),
47789
- saving = _useState46[0],
47790
- setSaving = _useState46[1];
47791
- var _useState47 = React.useState(null),
47945
+ pickBot = _useState46[0],
47946
+ setPickBot = _useState46[1];
47947
+ var _useState47 = React.useState(""),
47792
47948
  _useState48 = _slicedToArray(_useState47, 2),
47793
- error = _useState48[0],
47794
- setError = _useState48[1];
47949
+ pickEvent = _useState48[0],
47950
+ setPickEvent = _useState48[1];
47951
+ var _useState49 = React.useState(false),
47952
+ _useState50 = _slicedToArray(_useState49, 2),
47953
+ saving = _useState50[0],
47954
+ setSaving = _useState50[1];
47955
+ var _useState51 = React.useState(null),
47956
+ _useState52 = _slicedToArray(_useState51, 2),
47957
+ error = _useState52[0],
47958
+ setError = _useState52[1];
47795
47959
 
47796
47960
  // Discover the user's configured MCP providers — running or not. The bot
47797
47961
  // starts any that aren't running when it runs.
@@ -47913,9 +48077,22 @@ var BotDetail = function BotDetail(_ref) {
47913
48077
  var pickedWidget = pickedWs ? pickedWs.widgets.find(function (w) {
47914
48078
  return "".concat(w.ref, "|").concat(w.instanceId) === pickWidget;
47915
48079
  }) : null;
48080
+
48081
+ // Other bots' events, derived from their providers + tools (this bot
48082
+ // excluded — it can't trigger itself).
48083
+ var botCatalog = React.useMemo(function () {
48084
+ return buildBotEventCatalog(bots, toolSources, (bot === null || bot === void 0 ? void 0 : bot.id) || null);
48085
+ }, [bots, toolSources, bot === null || bot === void 0 ? void 0 : bot.id]);
48086
+ var pickedBot = botCatalog.find(function (b) {
48087
+ return b.botId === pickBot;
48088
+ }) || null;
48089
+ var pickedBotEvent = pickedBot ? pickedBot.events.find(function (e) {
48090
+ return e.event === pickEvent;
48091
+ }) || null : null;
48092
+ var canAddEvent = pickFrom === "bot" ? !!pickedBotEvent : !!(pickedWidget && pickEvent);
47916
48093
  var addSubscription = function addSubscription() {
47917
- if (!pickedWs || !pickedWidget || !pickEvent) return;
47918
- var sub = widgetSubscription(pickedWs, pickedWidget, pickEvent);
48094
+ if (!canAddEvent) return;
48095
+ var sub = pickFrom === "bot" ? botSubscription(pickedBot, pickedBotEvent) : widgetSubscription(pickedWs, pickedWidget, pickEvent);
47919
48096
  setSubscriptions(function (prev) {
47920
48097
  return prev.some(function (s) {
47921
48098
  return s.eventType === sub.eventType;
@@ -48198,16 +48375,17 @@ var BotDetail = function BotDetail(_ref) {
48198
48375
  }), subscriptions.length ? /*#__PURE__*/jsxRuntime.jsx("div", {
48199
48376
  className: "flex flex-col gap-1",
48200
48377
  children: subscriptions.map(function (sub) {
48201
- var _describeSubscription = describeSubscription(sub, eventCatalog),
48378
+ var _describeSubscription = describeSubscription(sub, eventCatalog, botCatalog),
48202
48379
  label = _describeSubscription.label,
48203
- missing = _describeSubscription.missing;
48380
+ missing = _describeSubscription.missing,
48381
+ kind = _describeSubscription.kind;
48204
48382
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
48205
48383
  className: "flex flex-row items-center justify-between gap-2",
48206
48384
  children: [/*#__PURE__*/jsxRuntime.jsxs("span", {
48207
48385
  className: "text-sm",
48208
48386
  children: [label, missing ? /*#__PURE__*/jsxRuntime.jsxs("span", {
48209
48387
  className: "text-xs opacity-60",
48210
- children: [" ", "(widget missing)"]
48388
+ children: [" ", "(", kind === "bot" ? "bot" : "widget", " missing)"]
48211
48389
  }) : null]
48212
48390
  }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button3, {
48213
48391
  title: "Remove",
@@ -48222,7 +48400,51 @@ var BotDetail = function BotDetail(_ref) {
48222
48400
  }) : /*#__PURE__*/jsxRuntime.jsx("span", {
48223
48401
  className: "text-xs opacity-50",
48224
48402
  children: "This bot doesn't run on any events yet."
48225
- }), eventCatalog.length ? /*#__PURE__*/jsxRuntime.jsxs("div", {
48403
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.SelectInput, {
48404
+ label: "From",
48405
+ value: pickFrom,
48406
+ onChange: function onChange(v) {
48407
+ setPickFrom(v);
48408
+ setPickEvent("");
48409
+ },
48410
+ options: EVENT_FROM_OPTIONS
48411
+ }), pickFrom === "bot" ? botCatalog.length ? /*#__PURE__*/jsxRuntime.jsxs("div", {
48412
+ className: "flex flex-col gap-2",
48413
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SelectInput, {
48414
+ label: "Bot",
48415
+ value: pickBot,
48416
+ onChange: function onChange(v) {
48417
+ setPickBot(v);
48418
+ setPickEvent("");
48419
+ },
48420
+ placeholder: "Choose a bot\u2026",
48421
+ options: botCatalog.map(function (b) {
48422
+ return {
48423
+ value: b.botId,
48424
+ label: b.name
48425
+ };
48426
+ })
48427
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.SelectInput, {
48428
+ label: "Event",
48429
+ value: pickEvent,
48430
+ onChange: setPickEvent,
48431
+ placeholder: "Choose an event\u2026",
48432
+ options: (pickedBot ? pickedBot.events : []).map(function (e) {
48433
+ return {
48434
+ value: e.event,
48435
+ label: e.label
48436
+ };
48437
+ })
48438
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
48439
+ title: "Add event",
48440
+ onClick: addSubscription,
48441
+ size: "sm",
48442
+ disabled: !canAddEvent
48443
+ })]
48444
+ }) : /*#__PURE__*/jsxRuntime.jsx("span", {
48445
+ className: "text-xs opacity-50",
48446
+ children: "No other bots yet. Create another bot to trigger this one when it finishes or uses a tool."
48447
+ }) : eventCatalog.length ? /*#__PURE__*/jsxRuntime.jsxs("div", {
48226
48448
  className: "flex flex-col gap-2",
48227
48449
  children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SelectInput, {
48228
48450
  label: "Dashboard",
@@ -48482,6 +48704,7 @@ var BotsSection = function BotsSection(_ref) {
48482
48704
  providers: providers,
48483
48705
  workspaces: workspaces,
48484
48706
  getWidgetConfig: getWidgetConfig,
48707
+ bots: bots,
48485
48708
  onSave: handleSave,
48486
48709
  onCancel: function onCancel() {
48487
48710
  return setIsCreating(false);
@@ -48493,6 +48716,7 @@ var BotsSection = function BotsSection(_ref) {
48493
48716
  providers: providers,
48494
48717
  workspaces: workspaces,
48495
48718
  getWidgetConfig: getWidgetConfig,
48719
+ bots: bots,
48496
48720
  onSave: handleSave,
48497
48721
  onDelete: function onDelete() {
48498
48722
  return setDeleteTarget(selected.id);