@plmbr/notebook-intelligence 5.0.1 → 5.1.0-a.1

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.
@@ -0,0 +1,44 @@
1
+ import { UUID } from '@lumino/coreutils';
2
+ import { ResponseStreamDataType } from './tokens';
3
+
4
+ /**
5
+ * The subset of a chat message's stream-content item this helper needs. A
6
+ * structural subset of `IChatMessageContent` (defined in chat-sidebar) so it
7
+ * can be unit-tested without importing the sidebar (and creating a cycle).
8
+ */
9
+ export interface IToolCallStreamItem {
10
+ id: string;
11
+ type: ResponseStreamDataType;
12
+ content: any;
13
+ created: Date;
14
+ }
15
+
16
+ /**
17
+ * Merge a streamed tool-call payload into `contents` by its tool-call id.
18
+ *
19
+ * A tool call streams twice under one id (once when it starts, once when it
20
+ * finishes). The first emission pushes a new card; the second updates that
21
+ * card's content (its status) in place, so the call stays a single persistent
22
+ * row rather than appending a duplicate. Mutates `contents`.
23
+ */
24
+ export function upsertToolCallContent(
25
+ contents: IToolCallStreamItem[],
26
+ content: { id: string; [key: string]: any },
27
+ created: Date
28
+ ): void {
29
+ const existing = contents.find(
30
+ c =>
31
+ c.type === ResponseStreamDataType.ToolCall &&
32
+ c.content?.id === content?.id
33
+ );
34
+ if (existing) {
35
+ existing.content = content;
36
+ } else {
37
+ contents.push({
38
+ id: UUID.uuid4(),
39
+ type: ResponseStreamDataType.ToolCall,
40
+ content,
41
+ created
42
+ });
43
+ }
44
+ }
package/src/utils.ts CHANGED
@@ -407,10 +407,11 @@ export function safeAnchorUri(uri: string | undefined | null): string | null {
407
407
  * user happens to be in the JupyterLab working directory.
408
408
  */
409
409
  export function buildResumeCommand(cwd: string, sessionId: string): string {
410
+ const quotedSessionId = shellSingleQuote(sessionId);
410
411
  if (!cwd) {
411
- return `claude --resume ${sessionId}`;
412
+ return `claude --resume ${quotedSessionId}`;
412
413
  }
413
- return `cd ${shellSingleQuote(cwd)} && claude --resume ${sessionId}`;
414
+ return `cd ${shellSingleQuote(cwd)} && claude --resume ${quotedSessionId}`;
414
415
  }
415
416
 
416
417
  /**
package/style/base.css CHANGED
@@ -643,6 +643,7 @@ pre:has(.code-block-header) {
643
643
 
644
644
  .chat-message-feedback:focus-within,
645
645
  .chat-message-feedback:has(.selected),
646
+ .chat-message-feedback.always-visible,
646
647
  .chat-message:hover .chat-message-feedback {
647
648
  opacity: 1;
648
649
  }
@@ -779,6 +780,169 @@ pre:has(.code-block-header) {
779
780
  margin-top: 2px;
780
781
  }
781
782
 
783
+ .nbi-tool-call-wrapper {
784
+ margin: 2px 0;
785
+ }
786
+
787
+ .nbi-tool-call {
788
+ display: flex;
789
+ align-items: center;
790
+ gap: 6px;
791
+ padding: 3px 6px;
792
+ border-radius: 4px;
793
+ background-color: var(--jp-layout-color2);
794
+ font-size: var(--jp-ui-font-size1);
795
+ }
796
+
797
+ .nbi-tool-call-kind-icon {
798
+ flex-shrink: 0;
799
+ color: var(--jp-ui-font-color2);
800
+ }
801
+
802
+ .nbi-tool-call-title {
803
+ flex: 1;
804
+ min-width: 0;
805
+ overflow: hidden;
806
+ white-space: nowrap;
807
+ text-overflow: ellipsis;
808
+ }
809
+
810
+ .nbi-tool-call-status-icon {
811
+ flex-shrink: 0;
812
+ color: var(--jp-ui-font-color2);
813
+ }
814
+
815
+ .nbi-tool-call-completed .nbi-tool-call-status-icon {
816
+ color: var(--jp-success-color1);
817
+ }
818
+
819
+ .nbi-tool-call-failed .nbi-tool-call-status-icon {
820
+ color: var(--jp-error-color1);
821
+ }
822
+
823
+ .nbi-tool-call-in-progress .nbi-tool-call-status-icon {
824
+ animation: nbi-tool-call-spin 1s linear infinite;
825
+ }
826
+
827
+ @keyframes nbi-tool-call-spin {
828
+ from {
829
+ transform: rotate(0deg);
830
+ }
831
+
832
+ to {
833
+ transform: rotate(360deg);
834
+ }
835
+ }
836
+
837
+ @media (prefers-reduced-motion: reduce) {
838
+ .nbi-tool-call-in-progress .nbi-tool-call-status-icon {
839
+ animation: none;
840
+ }
841
+ }
842
+
843
+ .nbi-tool-call-diff-toggle {
844
+ display: flex;
845
+ flex-shrink: 0;
846
+ align-items: center;
847
+ padding: 0;
848
+ border: none;
849
+ background: none;
850
+ color: var(--jp-ui-font-color2);
851
+ cursor: pointer;
852
+ }
853
+
854
+ .nbi-tool-call-diffs {
855
+ margin: 2px 0 2px 18px;
856
+ padding-left: 6px;
857
+ border-left: 2px solid var(--jp-border-color2);
858
+ }
859
+
860
+ .nbi-tool-call-diff + .nbi-tool-call-diff {
861
+ margin-top: 4px;
862
+ }
863
+
864
+ .nbi-tool-call-diff-path {
865
+ overflow: hidden;
866
+ font-size: var(--jp-ui-font-size0);
867
+ color: var(--jp-ui-font-color2);
868
+ white-space: nowrap;
869
+ text-overflow: ellipsis;
870
+ }
871
+
872
+ .nbi-tool-call-diff-body {
873
+ margin: 2px 0;
874
+ overflow-x: auto;
875
+ font-family: var(--jp-code-font-family);
876
+ font-size: var(--jp-code-font-size);
877
+ line-height: 1.4;
878
+ }
879
+
880
+ .nbi-tool-call-diff-line {
881
+ display: flex;
882
+ }
883
+
884
+ .nbi-diff-gutter {
885
+ flex-shrink: 0;
886
+ width: 1ch;
887
+ user-select: none;
888
+ text-align: center;
889
+ }
890
+
891
+ .nbi-diff-text {
892
+ white-space: pre-wrap;
893
+ word-break: break-word;
894
+ }
895
+
896
+ /* Semi-transparent tints rather than the solid --jp-*-color3 fills (which are
897
+ light pastels in BOTH themes): the tint sits over the card background so the
898
+ line stays readable with the theme's own (light-on-dark / dark-on-light)
899
+ text color instead of forcing dark text onto a pale fill. */
900
+ .nbi-diff-add {
901
+ background-color: rgb(64 160 43 / 22%);
902
+ }
903
+
904
+ .nbi-diff-remove {
905
+ background-color: rgb(248 81 73 / 22%);
906
+ }
907
+
908
+ .nbi-diff-context {
909
+ color: var(--jp-ui-font-color2);
910
+ }
911
+
912
+ .nbi-tool-call-diff-truncated {
913
+ font-size: var(--jp-ui-font-size0);
914
+ font-style: italic;
915
+ color: var(--jp-ui-font-color2);
916
+ }
917
+
918
+ .nbi-tool-call-group {
919
+ margin: 2px 0;
920
+ }
921
+
922
+ .nbi-tool-call-group-header {
923
+ display: flex;
924
+ align-items: center;
925
+ gap: 4px;
926
+ width: 100%;
927
+ padding: 2px 4px;
928
+ border: none;
929
+ background: none;
930
+ color: var(--jp-ui-font-color2);
931
+ font-size: var(--jp-ui-font-size0);
932
+ text-align: left;
933
+ cursor: pointer;
934
+ }
935
+
936
+ .nbi-tool-call-group-summary {
937
+ overflow: hidden;
938
+ white-space: nowrap;
939
+ text-overflow: ellipsis;
940
+ }
941
+
942
+ .nbi-tool-call-group-body {
943
+ margin-left: 6px;
944
+ }
945
+
782
946
  .user-input-autocomplete,
783
947
  .mode-tools-popover,
784
948
  .workspace-file-popover {
@@ -1503,12 +1667,17 @@ button.send-button:disabled:active:not(.send-button-stop) {
1503
1667
  .expandable-content-text {
1504
1668
  display: none;
1505
1669
  margin: 5px;
1506
- padding: 0 5px;
1507
- border: 1px solid var(--jp-border-color2);
1508
- border-radius: 5px;
1670
+ padding: 8px 10px;
1671
+ border-radius: 6px;
1509
1672
  max-height: 200px;
1510
1673
  overflow-y: auto;
1511
- box-shadow: inset 0 0 15px 15px rgb(23 23 23 / 50%);
1674
+ background-color: var(--jp-layout-color2);
1675
+ }
1676
+
1677
+ /* Inline code also fills with --jp-layout-color2, which now matches this box's
1678
+ fill; recess nested code to --jp-layout-color1 so it stays distinct. */
1679
+ .expandable-content-text :not(pre) > code {
1680
+ background-color: var(--jp-layout-color1);
1512
1681
  }
1513
1682
 
1514
1683
  .expandable-content .collapsed-icon {