@optilogic/chat 1.0.0-beta.1 → 1.0.0-beta.2

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.cjs CHANGED
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var React = require('react');
3
+ var React7 = require('react');
4
4
  var core = require('@optilogic/core');
5
5
  var lucideReact = require('lucide-react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
+ var editor = require('@optilogic/editor');
7
8
 
8
9
  function _interopNamespace(e) {
9
10
  if (e && e.__esModule) return e;
@@ -23,10 +24,10 @@ function _interopNamespace(e) {
23
24
  return Object.freeze(n);
24
25
  }
25
26
 
26
- var React__namespace = /*#__PURE__*/_interopNamespace(React);
27
+ var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
27
28
 
28
29
  // src/components/agent-response/AgentResponse.tsx
29
- var ActivityIndicators = React__namespace.forwardRef(
30
+ var ActivityIndicators = React7__namespace.forwardRef(
30
31
  ({ toolCalls, knowledge, memory, className, ...props }, ref) => {
31
32
  const hasAnyActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0;
32
33
  if (!hasAnyActivity) return null;
@@ -125,7 +126,7 @@ function formatTotalTime(seconds) {
125
126
  const minutes = seconds / 60;
126
127
  return `${minutes.toFixed(1)}m`;
127
128
  }
128
- var MetadataRow = React__namespace.forwardRef(
129
+ var MetadataRow = React7__namespace.forwardRef(
129
130
  ({
130
131
  hasThinking,
131
132
  isExpanded,
@@ -189,7 +190,7 @@ var MetadataRow = React__namespace.forwardRef(
189
190
  }
190
191
  );
191
192
  MetadataRow.displayName = "MetadataRow";
192
- var ThinkingSection = React__namespace.forwardRef(
193
+ var ThinkingSection = React7__namespace.forwardRef(
193
194
  ({ content, isExpanded, className, ...props }, ref) => {
194
195
  if (!isExpanded || !content) {
195
196
  return null;
@@ -206,7 +207,7 @@ var ThinkingSection = React__namespace.forwardRef(
206
207
  }
207
208
  );
208
209
  ThinkingSection.displayName = "ThinkingSection";
209
- var ActionBar = React__namespace.forwardRef(
210
+ var ActionBar = React7__namespace.forwardRef(
210
211
  ({
211
212
  response,
212
213
  isVisible,
@@ -217,8 +218,8 @@ var ActionBar = React__namespace.forwardRef(
217
218
  className,
218
219
  ...props
219
220
  }, ref) => {
220
- const [copied, setCopied] = React.useState(false);
221
- const handleCopy = React.useCallback(async () => {
221
+ const [copied, setCopied] = React7.useState(false);
222
+ const handleCopy = React7.useCallback(async () => {
222
223
  try {
223
224
  await navigator.clipboard.writeText(response);
224
225
  setCopied(true);
@@ -228,11 +229,11 @@ var ActionBar = React__namespace.forwardRef(
228
229
  console.error("Failed to copy response:", err);
229
230
  }
230
231
  }, [response, onResponseCopy]);
231
- const handleThumbsUp = React.useCallback(() => {
232
+ const handleThumbsUp = React7.useCallback(() => {
232
233
  const newValue = feedback === "up" ? null : "up";
233
234
  onFeedbackChange?.(newValue);
234
235
  }, [feedback, onFeedbackChange]);
235
- const handleThumbsDown = React.useCallback(() => {
236
+ const handleThumbsDown = React7.useCallback(() => {
236
237
  const newValue = feedback === "down" ? null : "down";
237
238
  onFeedbackChange?.(newValue);
238
239
  }, [feedback, onFeedbackChange]);
@@ -300,8 +301,8 @@ function useThinkingTimer({
300
301
  endTime,
301
302
  status
302
303
  }) {
303
- const [elapsed, setElapsed] = React.useState(0);
304
- React.useEffect(() => {
304
+ const [elapsed, setElapsed] = React7.useState(0);
305
+ React7.useEffect(() => {
305
306
  if (!startTime) {
306
307
  setElapsed(0);
307
308
  return;
@@ -337,9 +338,9 @@ var initialAgentResponseState = {
337
338
 
338
339
  // src/components/agent-response/hooks/useAgentResponseAccumulator.ts
339
340
  function useAgentResponseAccumulator(options) {
340
- const [state, setState] = React.useState(initialAgentResponseState);
341
+ const [state, setState] = React7.useState(initialAgentResponseState);
341
342
  const topic = options?.topic;
342
- const handleMessage = React.useCallback(
343
+ const handleMessage = React7.useCallback(
343
344
  (message) => {
344
345
  let payload;
345
346
  if (topic) {
@@ -443,12 +444,12 @@ function useAgentResponseAccumulator(options) {
443
444
  },
444
445
  [topic]
445
446
  );
446
- const reset = React.useCallback(() => {
447
+ const reset = React7.useCallback(() => {
447
448
  setState(initialAgentResponseState);
448
449
  }, []);
449
450
  return { state, handleMessage, reset };
450
451
  }
451
- var AgentResponse = React__namespace.forwardRef(
452
+ var AgentResponse = React7__namespace.forwardRef(
452
453
  ({
453
454
  state,
454
455
  id,
@@ -464,10 +465,10 @@ var AgentResponse = React__namespace.forwardRef(
464
465
  className,
465
466
  ...props
466
467
  }, ref) => {
467
- const [uncontrolledExpanded, setUncontrolledExpanded] = React.useState(defaultThinkingExpanded);
468
+ const [uncontrolledExpanded, setUncontrolledExpanded] = React7.useState(defaultThinkingExpanded);
468
469
  const isThinkingControlled = controlledThinkingExpanded !== void 0;
469
470
  const thinkingExpanded = isThinkingControlled ? controlledThinkingExpanded : uncontrolledExpanded;
470
- const toggleThinking = React.useCallback(() => {
471
+ const toggleThinking = React7.useCallback(() => {
471
472
  const newValue = !thinkingExpanded;
472
473
  if (isThinkingControlled) {
473
474
  onThinkingExpandedChange?.(newValue);
@@ -475,13 +476,13 @@ var AgentResponse = React__namespace.forwardRef(
475
476
  setUncontrolledExpanded(newValue);
476
477
  }
477
478
  }, [thinkingExpanded, isThinkingControlled, onThinkingExpandedChange]);
478
- const [isHovered, setIsHovered] = React.useState(false);
479
+ const [isHovered, setIsHovered] = React7.useState(false);
479
480
  const elapsedTime = useThinkingTimer({
480
481
  startTime: state.thinkingStartTime,
481
482
  endTime: state.responseCompleteTime,
482
483
  status: state.status
483
484
  });
484
- const totalTimeSeconds = React.useMemo(() => {
485
+ const totalTimeSeconds = React7.useMemo(() => {
485
486
  if (!state.firstMessageTime || !state.responseCompleteTime) return 0;
486
487
  return (state.responseCompleteTime - state.firstMessageTime) / 1e3;
487
488
  }, [state.firstMessageTime, state.responseCompleteTime]);
@@ -552,12 +553,223 @@ var AgentResponse = React__namespace.forwardRef(
552
553
  }
553
554
  );
554
555
  AgentResponse.displayName = "AgentResponse";
556
+ var UserPrompt = React7__namespace.forwardRef(
557
+ ({ content, timestamp, className, ...props }, ref) => {
558
+ return /* @__PURE__ */ jsxRuntime.jsxs(
559
+ "div",
560
+ {
561
+ ref,
562
+ className: core.cn(
563
+ "w-fit max-w-[80%] rounded-lg px-4 pt-3.5 pb-3",
564
+ "bg-secondary text-secondary-foreground",
565
+ className
566
+ ),
567
+ ...props,
568
+ children: [
569
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap", children: content }),
570
+ timestamp && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-secondary-foreground/70 mt-1", children: timestamp.toLocaleTimeString([], {
571
+ hour: "2-digit",
572
+ minute: "2-digit"
573
+ }) })
574
+ ]
575
+ }
576
+ );
577
+ }
578
+ );
579
+ UserPrompt.displayName = "UserPrompt";
580
+ function createCodeBlockDecorate(entry) {
581
+ const [node, path] = entry;
582
+ const ranges = [];
583
+ if (!editor.Text.isText(node)) {
584
+ return ranges;
585
+ }
586
+ const { text } = node;
587
+ const backtickPositions = [];
588
+ let searchStart = 0;
589
+ while (true) {
590
+ const pos = text.indexOf("```", searchStart);
591
+ if (pos === -1) break;
592
+ backtickPositions.push(pos);
593
+ searchStart = pos + 3;
594
+ }
595
+ let i = 0;
596
+ while (i < backtickPositions.length) {
597
+ const openPos = backtickPositions[i];
598
+ const closePos = backtickPositions[i + 1];
599
+ ranges.push({
600
+ anchor: { path, offset: openPos },
601
+ focus: { path, offset: openPos + 3 },
602
+ codeDelimiter: true
603
+ });
604
+ if (closePos !== void 0) {
605
+ if (closePos > openPos + 3) {
606
+ ranges.push({
607
+ anchor: { path, offset: openPos + 3 },
608
+ focus: { path, offset: closePos },
609
+ codeBlock: true
610
+ });
611
+ }
612
+ ranges.push({
613
+ anchor: { path, offset: closePos },
614
+ focus: { path, offset: closePos + 3 },
615
+ codeDelimiter: true
616
+ });
617
+ i += 2;
618
+ } else {
619
+ if (text.length > openPos + 3) {
620
+ ranges.push({
621
+ anchor: { path, offset: openPos + 3 },
622
+ focus: { path, offset: text.length },
623
+ codeBlock: true
624
+ });
625
+ }
626
+ i += 1;
627
+ }
628
+ }
629
+ return ranges;
630
+ }
631
+ function CodeBlockLeaf({ attributes, children, leaf }) {
632
+ const leafAny = leaf;
633
+ if (leafAny.codeBlock) {
634
+ return /* @__PURE__ */ jsxRuntime.jsx(
635
+ "span",
636
+ {
637
+ ...attributes,
638
+ className: "bg-muted/50 text-muted-foreground font-mono text-sm rounded px-1",
639
+ children
640
+ }
641
+ );
642
+ }
643
+ if (leafAny.codeDelimiter) {
644
+ return /* @__PURE__ */ jsxRuntime.jsx(
645
+ "span",
646
+ {
647
+ ...attributes,
648
+ className: "text-muted-foreground/50 font-mono text-sm",
649
+ children
650
+ }
651
+ );
652
+ }
653
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ...attributes, children });
654
+ }
655
+ var UserPromptInput = React7__namespace.forwardRef(
656
+ ({
657
+ value = "",
658
+ onChange,
659
+ onSubmit,
660
+ clearOnSubmit = true,
661
+ placeholder = "Type your message...",
662
+ disabled = false,
663
+ isSubmitting = false,
664
+ minRows = 1,
665
+ maxRows = 6,
666
+ renderActions,
667
+ enableTags = false,
668
+ onTagCreate,
669
+ onTagDelete,
670
+ className,
671
+ ...props
672
+ }, ref) => {
673
+ const editorRef = React7__namespace.useRef(null);
674
+ const [internalValue, setInternalValue] = React7__namespace.useState(value);
675
+ React7__namespace.useEffect(() => {
676
+ setInternalValue(value);
677
+ }, [value]);
678
+ React7__namespace.useImperativeHandle(
679
+ ref,
680
+ () => ({
681
+ focus: () => editorRef.current?.focus(),
682
+ clear: () => {
683
+ editorRef.current?.clear();
684
+ setInternalValue("");
685
+ },
686
+ getText: () => editorRef.current?.getText() ?? "",
687
+ insertText: (text) => editorRef.current?.insertText(text)
688
+ }),
689
+ []
690
+ );
691
+ const handleChange = React7__namespace.useCallback(
692
+ (newValue) => {
693
+ setInternalValue(newValue);
694
+ onChange?.(newValue);
695
+ },
696
+ [onChange]
697
+ );
698
+ const handleSubmit = React7__namespace.useCallback(
699
+ (text) => {
700
+ if (disabled || isSubmitting) return;
701
+ if (!text.trim()) return;
702
+ onSubmit?.(text.trim());
703
+ if (clearOnSubmit) {
704
+ editorRef.current?.clear();
705
+ setInternalValue("");
706
+ }
707
+ },
708
+ [disabled, isSubmitting, onSubmit, clearOnSubmit]
709
+ );
710
+ const handleSendClick = React7__namespace.useCallback(() => {
711
+ const text = editorRef.current?.getText() ?? "";
712
+ handleSubmit(text);
713
+ }, [handleSubmit]);
714
+ const hasContent = internalValue.trim().length > 0;
715
+ const canSubmit = hasContent && !disabled && !isSubmitting;
716
+ return /* @__PURE__ */ jsxRuntime.jsxs(
717
+ "div",
718
+ {
719
+ className: core.cn(
720
+ "rounded-lg border border-input bg-background",
721
+ disabled && "opacity-50 cursor-not-allowed",
722
+ className
723
+ ),
724
+ ...props,
725
+ children: [
726
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-2 pr-0 pt-1 pb-1", children: /* @__PURE__ */ jsxRuntime.jsx(
727
+ editor.SlateEditor,
728
+ {
729
+ ref: editorRef,
730
+ value: internalValue,
731
+ onChange: handleChange,
732
+ onSubmit: handleSubmit,
733
+ clearOnSubmit: false,
734
+ placeholder,
735
+ disabled: disabled || isSubmitting,
736
+ enableTags,
737
+ onTagCreate,
738
+ onTagDelete,
739
+ minRows,
740
+ maxRows,
741
+ decorate: createCodeBlockDecorate,
742
+ renderLeaf: CodeBlockLeaf
743
+ }
744
+ ) }),
745
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pl-2 pr-1 pb-1 pt-1", children: [
746
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: renderActions?.() }),
747
+ /* @__PURE__ */ jsxRuntime.jsx(
748
+ core.IconButton,
749
+ {
750
+ icon: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, {}),
751
+ variant: "filled",
752
+ size: "sm",
753
+ "aria-label": isSubmitting ? "Sending..." : "Send message",
754
+ disabled: !canSubmit,
755
+ onClick: handleSendClick
756
+ }
757
+ )
758
+ ] })
759
+ ]
760
+ }
761
+ );
762
+ }
763
+ );
764
+ UserPromptInput.displayName = "UserPromptInput";
555
765
 
556
766
  exports.ActionBar = ActionBar;
557
767
  exports.ActivityIndicators = ActivityIndicators;
558
768
  exports.AgentResponse = AgentResponse;
559
769
  exports.MetadataRow = MetadataRow;
560
770
  exports.ThinkingSection = ThinkingSection;
771
+ exports.UserPrompt = UserPrompt;
772
+ exports.UserPromptInput = UserPromptInput;
561
773
  exports.formatTime = formatTime;
562
774
  exports.formatTotalTime = formatTotalTime;
563
775
  exports.initialAgentResponseState = initialAgentResponseState;