@trops/dash-core 0.1.380 → 0.1.382

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.esm.js CHANGED
@@ -56535,10 +56535,18 @@ function AssistantTextContent(_ref) {
56535
56535
  var MessageBubble = function MessageBubble(_ref2) {
56536
56536
  var message = _ref2.message,
56537
56537
  isStreaming = _ref2.isStreaming,
56538
- streamingText = _ref2.streamingText;
56538
+ streamingText = _ref2.streamingText,
56539
+ _ref2$isLast = _ref2.isLast,
56540
+ isLast = _ref2$isLast === void 0 ? false : _ref2$isLast;
56539
56541
  var role = message.role,
56540
56542
  content = message.content,
56541
- toolCalls = message.toolCalls;
56543
+ toolCalls = message.toolCalls,
56544
+ hidden = message.hidden;
56545
+
56546
+ // App-injected priming messages (e.g. widget-builder "Hello…" seed)
56547
+ // are kept in state for conversation continuity but suppressed from
56548
+ // the rendered timeline — the user sees only the agent's reply.
56549
+ if (hidden) return null;
56542
56550
  if (role === "user") {
56543
56551
  var text = typeof content === "string" ? content : Array.isArray(content) ? content.filter(function (c) {
56544
56552
  return c.type === "text";
@@ -56593,12 +56601,51 @@ var MessageBubble = function MessageBubble(_ref2) {
56593
56601
  } else if (typeof content === "string") {
56594
56602
  textParts.push(content);
56595
56603
  }
56604
+
56605
+ // Fallback: CLI backend (Claude Code) tracks tool calls on the
56606
+ // message's `toolCalls` field without placing tool_use blocks in
56607
+ // `content`. If we found no tool blocks in content but have toolCalls,
56608
+ // render those directly so the user sees what Claude is doing.
56609
+ if (toolBlocks.length === 0 && Array.isArray(toolCalls)) {
56610
+ var _iterator2 = _createForOfIteratorHelper$1(toolCalls),
56611
+ _step2;
56612
+ try {
56613
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
56614
+ var tc = _step2.value;
56615
+ toolBlocks.push({
56616
+ id: tc.toolUseId,
56617
+ name: tc.toolName,
56618
+ input: tc.input,
56619
+ serverName: tc.serverName,
56620
+ result: tc.result,
56621
+ isError: tc.isError,
56622
+ isLoading: tc.isLoading
56623
+ });
56624
+ }
56625
+ } catch (err) {
56626
+ _iterator2.e(err);
56627
+ } finally {
56628
+ _iterator2.f();
56629
+ }
56630
+ }
56596
56631
  var _text = textParts.join("");
56597
56632
 
56598
- // Hide empty assistant bubbles (e.g., tool-use-only responses from
56599
- // the CLI backend where content is [] and tool calls are tracked
56600
- // separately). Nothing useful to show the user.
56633
+ // Hide empty assistant bubbles (tool-use-only responses from the
56634
+ // CLI backend). But if this is the LAST message, show a thinking
56635
+ // indicator so the user knows the AI is working.
56601
56636
  if (!isStreaming && !_text && toolBlocks.length === 0) {
56637
+ if (isLast) {
56638
+ return /*#__PURE__*/jsxs("div", {
56639
+ className: "mb-4",
56640
+ children: [/*#__PURE__*/jsx("div", {
56641
+ className: "text-[10px] font-semibold uppercase tracking-wider text-gray-500 mb-1",
56642
+ children: "Assistant"
56643
+ }), /*#__PURE__*/jsx("div", {
56644
+ className: "text-sm leading-relaxed px-3 py-2 rounded-lg bg-gray-800/40 text-gray-500 italic",
56645
+ children: "Thinking..."
56646
+ })]
56647
+ });
56648
+ }
56602
56649
  return null;
56603
56650
  }
56604
56651
  return /*#__PURE__*/jsxs("div", {
@@ -56638,9 +56685,12 @@ var MessageBubble = function MessageBubble(_ref2) {
56638
56685
  * Scrollable message list that auto-scrolls to the bottom on new messages.
56639
56686
  */
56640
56687
  var ChatMessages = function ChatMessages(_ref) {
56688
+ var _messages;
56641
56689
  var messages = _ref.messages,
56642
56690
  streamingRequestId = _ref.streamingRequestId,
56643
- streamingText = _ref.streamingText;
56691
+ streamingText = _ref.streamingText,
56692
+ _ref$isLoading = _ref.isLoading,
56693
+ isLoading = _ref$isLoading === void 0 ? false : _ref$isLoading;
56644
56694
  var scrollRef = useRef(null);
56645
56695
  useEffect(function () {
56646
56696
  if (scrollRef.current) {
@@ -56661,18 +56711,46 @@ var ChatMessages = function ChatMessages(_ref) {
56661
56711
  })
56662
56712
  });
56663
56713
  }
56664
- return /*#__PURE__*/jsx("div", {
56714
+ return /*#__PURE__*/jsxs("div", {
56665
56715
  ref: scrollRef,
56666
56716
  className: "flex-1 overflow-y-auto px-4 py-3 scroll-smooth",
56667
- children: messages.map(function (message, index) {
56717
+ children: [messages.map(function (message, index) {
56668
56718
  var isLastAssistant = message.role === "assistant" && index === messages.length - 1;
56669
56719
  var isStreaming = isLastAssistant && streamingRequestId !== null;
56670
56720
  return /*#__PURE__*/jsx(MessageBubble, {
56671
56721
  message: message,
56672
56722
  isStreaming: isStreaming,
56673
- streamingText: isStreaming ? streamingText : ""
56723
+ streamingText: isStreaming ? streamingText : "",
56724
+ isLast: index === messages.length - 1
56674
56725
  }, message.id || index);
56675
- })
56726
+ }), isLoading && !streamingRequestId && ((_messages = messages[messages.length - 1]) === null || _messages === void 0 ? void 0 : _messages.role) === "user" && /*#__PURE__*/jsxs("div", {
56727
+ className: "mb-4",
56728
+ children: [/*#__PURE__*/jsx("div", {
56729
+ className: "text-[10px] font-semibold uppercase tracking-wider text-gray-500 mb-1",
56730
+ children: "Assistant"
56731
+ }), /*#__PURE__*/jsxs("div", {
56732
+ className: "text-sm leading-relaxed px-3 py-2 rounded-lg bg-gray-800/40 text-gray-500 italic flex items-center gap-2",
56733
+ children: [/*#__PURE__*/jsxs("span", {
56734
+ className: "inline-flex gap-0.5",
56735
+ children: [/*#__PURE__*/jsx("span", {
56736
+ className: "w-1.5 h-1.5 bg-gray-500 rounded-full animate-bounce",
56737
+ style: {
56738
+ animationDelay: "0ms"
56739
+ }
56740
+ }), /*#__PURE__*/jsx("span", {
56741
+ className: "w-1.5 h-1.5 bg-gray-500 rounded-full animate-bounce",
56742
+ style: {
56743
+ animationDelay: "150ms"
56744
+ }
56745
+ }), /*#__PURE__*/jsx("span", {
56746
+ className: "w-1.5 h-1.5 bg-gray-500 rounded-full animate-bounce",
56747
+ style: {
56748
+ animationDelay: "300ms"
56749
+ }
56750
+ })]
56751
+ }), "Thinking..."]
56752
+ })]
56753
+ })]
56676
56754
  });
56677
56755
  };
56678
56756
 
@@ -56822,6 +56900,8 @@ function ChatCore(_ref) {
56822
56900
  uuid = _ref$uuid === void 0 ? null : _ref$uuid,
56823
56901
  _ref$persistKey = _ref.persistKey,
56824
56902
  persistKey = _ref$persistKey === void 0 ? null : _ref$persistKey,
56903
+ _ref$sessionKey = _ref.sessionKey,
56904
+ sessionKey = _ref$sessionKey === void 0 ? null : _ref$sessionKey,
56825
56905
  _ref$backend = _ref.backend,
56826
56906
  backend = _ref$backend === void 0 ? "anthropic" : _ref$backend,
56827
56907
  _ref$onPublishEvent = _ref.onPublishEvent,
@@ -56829,7 +56909,9 @@ function ChatCore(_ref) {
56829
56909
  _ref$hideToolsBanner = _ref.hideToolsBanner,
56830
56910
  hideToolsBanner = _ref$hideToolsBanner === void 0 ? false : _ref$hideToolsBanner,
56831
56911
  _ref$cwd = _ref.cwd,
56832
- cwd = _ref$cwd === void 0 ? null : _ref$cwd;
56912
+ cwd = _ref$cwd === void 0 ? null : _ref$cwd,
56913
+ _ref$initialMessage = _ref.initialMessage,
56914
+ initialMessage = _ref$initialMessage === void 0 ? null : _ref$initialMessage;
56833
56915
  var mainApi = window.mainApi;
56834
56916
 
56835
56917
  // Conversation state
@@ -56921,8 +57003,14 @@ function ChatCore(_ref) {
56921
57003
  } catch (e) {
56922
57004
  /* ignore quota errors */
56923
57005
  }
57006
+ } else if (sessionKey) {
57007
+ try {
57008
+ sessionStorage.setItem(sessionKey, JSON.stringify(data));
57009
+ } catch (e) {
57010
+ /* ignore quota errors */
57011
+ }
56924
57012
  }
56925
- }, [api, uuid, persistKey, enabledTools]);
57013
+ }, [api, uuid, persistKey, sessionKey, enabledTools]);
56926
57014
 
56927
57015
  // Load saved conversation on mount
56928
57016
  useEffect(function () {
@@ -56954,8 +57042,23 @@ function ChatCore(_ref) {
56954
57042
  } catch (e) {
56955
57043
  /* ignore */
56956
57044
  }
57045
+ } else if (sessionKey) {
57046
+ try {
57047
+ var _raw = sessionStorage.getItem(sessionKey);
57048
+ if (_raw) {
57049
+ var _data = JSON.parse(_raw);
57050
+ if (_data !== null && _data !== void 0 && _data.messages && Array.isArray(_data.messages)) {
57051
+ setMessages(_data.messages);
57052
+ }
57053
+ if (_data !== null && _data !== void 0 && _data.enabledTools) {
57054
+ setEnabledTools(_data.enabledTools);
57055
+ }
57056
+ }
57057
+ } catch (e) {
57058
+ /* ignore */
57059
+ }
56957
57060
  }
56958
- }, [api, uuid, persistKey]);
57061
+ }, [api, uuid, persistKey, sessionKey]);
56959
57062
 
56960
57063
  // Discover connected MCP tools (only for anthropic backend)
56961
57064
  var refreshTools = useCallback(function () {
@@ -57006,6 +57109,13 @@ function ChatCore(_ref) {
57006
57109
  tc.isError = data.isError;
57007
57110
  tc.isLoading = false;
57008
57111
  }
57112
+ // Force re-render so MessageBubble picks up the updated tool
57113
+ // result state (isLoading=false, result populated). Can't rely on
57114
+ // setStreamingText since it may already be empty (tool-only
57115
+ // response from CLI backend).
57116
+ setMessages(function (prev) {
57117
+ return _toConsumableArray(prev);
57118
+ });
57009
57119
  setStreamingText("");
57010
57120
  if (onPublishEvent) {
57011
57121
  onPublishEvent("toolUsed", {
@@ -57064,14 +57174,19 @@ function ChatCore(_ref) {
57064
57174
  };
57065
57175
  }, [mainApi, onPublishEvent, saveConversation]);
57066
57176
 
57067
- // Send message
57177
+ // Send message. `options.hidden` marks the user message so
57178
+ // MessageBubble skips rendering it — useful for app-injected
57179
+ // priming prompts where the agent's reply should appear first,
57180
+ // but the prompt still needs to be in conversation history.
57068
57181
  var handleSend = useCallback(function (text) {
57182
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
57069
57183
  if (!(mainApi !== null && mainApi !== void 0 && mainApi.llm) || isLoading) return;
57070
57184
  setError(null);
57071
57185
  var userMessage = {
57072
57186
  id: "msg-".concat(Date.now()),
57073
57187
  role: "user",
57074
- content: text
57188
+ content: text,
57189
+ hidden: options.hidden === true
57075
57190
  };
57076
57191
  var updatedMessages = [].concat(_toConsumableArray(messages), [userMessage]);
57077
57192
  setMessages(updatedMessages);
@@ -57116,7 +57231,7 @@ function ChatCore(_ref) {
57116
57231
  _iterator2.f();
57117
57232
  }
57118
57233
  }
57119
- var requestId = generateRequestId(uuid || persistKey);
57234
+ var requestId = generateRequestId(uuid || persistKey || sessionKey);
57120
57235
  activeRequestId.current = requestId;
57121
57236
  toolCallsRef.current = [];
57122
57237
  setIsLoading(true);
@@ -57138,7 +57253,7 @@ function ChatCore(_ref) {
57138
57253
  toolServerMap: toolServerMap,
57139
57254
  systemPrompt: systemPrompt,
57140
57255
  maxToolRounds: parseInt(maxToolRounds, 10) || 10,
57141
- widgetUuid: uuid || persistKey,
57256
+ widgetUuid: uuid || persistKey || sessionKey,
57142
57257
  cwd: cwd || undefined
57143
57258
  });
57144
57259
  }, [mainApi, isLoading, messages, servers, enabledTools, apiKey, model, systemPrompt, maxToolRounds, uuid, persistKey, onPublishEvent, backend, isAnthropicBackend]);
@@ -57181,6 +57296,27 @@ function ChatCore(_ref) {
57181
57296
  }
57182
57297
  }, [mainApi, streamingText, saveConversation]);
57183
57298
 
57299
+ // Auto-send an initial message once the chat is ready and empty.
57300
+ // Runs at most once per mount. Skipped if the conversation was
57301
+ // restored from persistence (messages already populated) or the
57302
+ // backend isn't ready yet.
57303
+ var initialMessageFiredRef = useRef(false);
57304
+ useEffect(function () {
57305
+ if (initialMessageFiredRef.current) return;
57306
+ if (!initialMessage) return;
57307
+ if (!(mainApi !== null && mainApi !== void 0 && mainApi.llm)) return;
57308
+ if (isLoading) return;
57309
+ if (messages.length !== 0) return;
57310
+ // CLI backend: wait for availability check to resolve.
57311
+ if (isCliBackend && cliAvailable === null) return;
57312
+ if (isCliBackend && !cliAvailable) return;
57313
+ initialMessageFiredRef.current = true;
57314
+ handleSend(initialMessage, {
57315
+ hidden: true
57316
+ });
57317
+ // eslint-disable-next-line react-hooks/exhaustive-deps
57318
+ }, [initialMessage, mainApi, messages, isCliBackend, cliAvailable, isLoading]);
57319
+
57184
57320
  // New chat
57185
57321
  var handleNewChat = function handleNewChat() {
57186
57322
  var _mainApi$llm3;
@@ -57191,7 +57327,7 @@ function ChatCore(_ref) {
57191
57327
  setSessionActive(false);
57192
57328
  saveConversation([]);
57193
57329
  if (isCliBackend && mainApi !== null && mainApi !== void 0 && (_mainApi$llm3 = mainApi.llm) !== null && _mainApi$llm3 !== void 0 && _mainApi$llm3.clearCliSession) {
57194
- mainApi.llm.clearCliSession(uuid || persistKey);
57330
+ mainApi.llm.clearCliSession(uuid || persistKey || sessionKey);
57195
57331
  }
57196
57332
  };
57197
57333
 
@@ -57200,7 +57336,7 @@ function ChatCore(_ref) {
57200
57336
  var _mainApi$llm4;
57201
57337
  if (!isCliBackend || !(mainApi !== null && mainApi !== void 0 && (_mainApi$llm4 = mainApi.llm) !== null && _mainApi$llm4 !== void 0 && _mainApi$llm4.endCliSession)) return;
57202
57338
  if (isLoading) handleStop();
57203
- mainApi.llm.endCliSession(uuid || persistKey);
57339
+ mainApi.llm.endCliSession(uuid || persistKey || sessionKey);
57204
57340
  setSessionActive(false);
57205
57341
  };
57206
57342
 
@@ -57311,7 +57447,8 @@ function ChatCore(_ref) {
57311
57447
  }), /*#__PURE__*/jsx(ChatMessages, {
57312
57448
  messages: messages,
57313
57449
  streamingRequestId: isLoading ? activeRequestId.current : null,
57314
- streamingText: streamingText
57450
+ streamingText: streamingText,
57451
+ isLoading: isLoading
57315
57452
  }), /*#__PURE__*/jsx(ChatInput, {
57316
57453
  onSend: handleSend,
57317
57454
  onStop: handleStop,