@plmbr/notebook-intelligence 5.0.0

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.
Files changed (137) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +412 -0
  3. package/lib/api.d.ts +288 -0
  4. package/lib/api.js +927 -0
  5. package/lib/cell-output-bundle.d.ts +25 -0
  6. package/lib/cell-output-bundle.js +129 -0
  7. package/lib/cell-output-toolbar.d.ts +26 -0
  8. package/lib/cell-output-toolbar.js +188 -0
  9. package/lib/chat-progress-feedback.d.ts +3 -0
  10. package/lib/chat-progress-feedback.js +27 -0
  11. package/lib/chat-sidebar.d.ts +92 -0
  12. package/lib/chat-sidebar.js +3452 -0
  13. package/lib/command-ids.d.ts +39 -0
  14. package/lib/command-ids.js +44 -0
  15. package/lib/components/ask-user-question.d.ts +2 -0
  16. package/lib/components/ask-user-question.js +85 -0
  17. package/lib/components/checkbox.d.ts +2 -0
  18. package/lib/components/checkbox.js +30 -0
  19. package/lib/components/claude-mcp-panel.d.ts +2 -0
  20. package/lib/components/claude-mcp-panel.js +275 -0
  21. package/lib/components/claude-mcp-paste.d.ts +7 -0
  22. package/lib/components/claude-mcp-paste.js +104 -0
  23. package/lib/components/claude-session-picker.d.ts +8 -0
  24. package/lib/components/claude-session-picker.js +127 -0
  25. package/lib/components/form-dialog.d.ts +25 -0
  26. package/lib/components/form-dialog.js +35 -0
  27. package/lib/components/launcher-picker.d.ts +6 -0
  28. package/lib/components/launcher-picker.js +135 -0
  29. package/lib/components/mcp-util.d.ts +2 -0
  30. package/lib/components/mcp-util.js +37 -0
  31. package/lib/components/notebook-generation-popover.d.ts +7 -0
  32. package/lib/components/notebook-generation-popover.js +60 -0
  33. package/lib/components/pill.d.ts +2 -0
  34. package/lib/components/pill.js +5 -0
  35. package/lib/components/plugins-panel.d.ts +3 -0
  36. package/lib/components/plugins-panel.js +466 -0
  37. package/lib/components/settings-panel.d.ts +11 -0
  38. package/lib/components/settings-panel.js +742 -0
  39. package/lib/components/skills-panel.d.ts +2 -0
  40. package/lib/components/skills-panel.js +1264 -0
  41. package/lib/handler.d.ts +8 -0
  42. package/lib/handler.js +36 -0
  43. package/lib/icons.d.ts +45 -0
  44. package/lib/icons.js +54 -0
  45. package/lib/index.d.ts +8 -0
  46. package/lib/index.js +2079 -0
  47. package/lib/markdown-renderer.d.ts +10 -0
  48. package/lib/markdown-renderer.js +64 -0
  49. package/lib/notebook-generation-toolbar.d.ts +16 -0
  50. package/lib/notebook-generation-toolbar.js +197 -0
  51. package/lib/notebook-generation.d.ts +8 -0
  52. package/lib/notebook-generation.js +12 -0
  53. package/lib/open-file-refresh-watcher-env.d.ts +4 -0
  54. package/lib/open-file-refresh-watcher-env.js +33 -0
  55. package/lib/open-file-refresh-watcher.d.ts +97 -0
  56. package/lib/open-file-refresh-watcher.js +190 -0
  57. package/lib/shell-utils.d.ts +6 -0
  58. package/lib/shell-utils.js +9 -0
  59. package/lib/task-target-notebook.d.ts +2 -0
  60. package/lib/task-target-notebook.js +28 -0
  61. package/lib/terminal-drag-format.d.ts +9 -0
  62. package/lib/terminal-drag-format.js +23 -0
  63. package/lib/terminal-drag.d.ts +12 -0
  64. package/lib/terminal-drag.js +268 -0
  65. package/lib/tokens.d.ts +149 -0
  66. package/lib/tokens.js +88 -0
  67. package/lib/tour/tour-anchors.d.ts +18 -0
  68. package/lib/tour/tour-anchors.js +18 -0
  69. package/lib/tour/tour-config.d.ts +66 -0
  70. package/lib/tour/tour-config.js +99 -0
  71. package/lib/tour/tour-defaults.json +58 -0
  72. package/lib/tour/tour-events.d.ts +19 -0
  73. package/lib/tour/tour-events.js +30 -0
  74. package/lib/tour/tour-overlay.d.ts +6 -0
  75. package/lib/tour/tour-overlay.js +350 -0
  76. package/lib/tour/tour-state.d.ts +20 -0
  77. package/lib/tour/tour-state.js +81 -0
  78. package/lib/tour/tour-steps.d.ts +33 -0
  79. package/lib/tour/tour-steps.js +216 -0
  80. package/lib/utils.d.ts +53 -0
  81. package/lib/utils.js +385 -0
  82. package/package.json +258 -0
  83. package/schema/plugin.json +42 -0
  84. package/src/api.ts +1424 -0
  85. package/src/cell-output-bundle.ts +176 -0
  86. package/src/cell-output-toolbar.ts +232 -0
  87. package/src/chat-progress-feedback.ts +35 -0
  88. package/src/chat-sidebar.tsx +5147 -0
  89. package/src/command-ids.ts +67 -0
  90. package/src/components/ask-user-question.tsx +151 -0
  91. package/src/components/checkbox.tsx +62 -0
  92. package/src/components/claude-mcp-panel.tsx +543 -0
  93. package/src/components/claude-mcp-paste.ts +132 -0
  94. package/src/components/claude-session-picker.tsx +214 -0
  95. package/src/components/form-dialog.tsx +75 -0
  96. package/src/components/launcher-picker.tsx +237 -0
  97. package/src/components/mcp-util.ts +53 -0
  98. package/src/components/notebook-generation-popover.tsx +127 -0
  99. package/src/components/pill.tsx +15 -0
  100. package/src/components/plugins-panel.tsx +774 -0
  101. package/src/components/settings-panel.tsx +1631 -0
  102. package/src/components/skills-panel.tsx +2084 -0
  103. package/src/handler.ts +51 -0
  104. package/src/icons.ts +71 -0
  105. package/src/index.ts +2583 -0
  106. package/src/markdown-renderer.tsx +153 -0
  107. package/src/notebook-generation-toolbar.tsx +281 -0
  108. package/src/notebook-generation.ts +23 -0
  109. package/src/open-file-refresh-watcher-env.ts +52 -0
  110. package/src/open-file-refresh-watcher.ts +260 -0
  111. package/src/shell-utils.ts +10 -0
  112. package/src/svg.d.ts +4 -0
  113. package/src/task-target-notebook.ts +37 -0
  114. package/src/terminal-drag-format.ts +29 -0
  115. package/src/terminal-drag.ts +382 -0
  116. package/src/tokens.ts +171 -0
  117. package/src/tour/tour-anchors.ts +21 -0
  118. package/src/tour/tour-config.ts +160 -0
  119. package/src/tour/tour-events.ts +34 -0
  120. package/src/tour/tour-overlay.tsx +474 -0
  121. package/src/tour/tour-state.ts +87 -0
  122. package/src/tour/tour-steps.ts +281 -0
  123. package/src/utils.ts +455 -0
  124. package/style/base.css +3238 -0
  125. package/style/icons/cell-toolbar-bug.svg +5 -0
  126. package/style/icons/cell-toolbar-chat.svg +5 -0
  127. package/style/icons/cell-toolbar-sparkle.svg +5 -0
  128. package/style/icons/claude.svg +1 -0
  129. package/style/icons/copilot-warning.svg +1 -0
  130. package/style/icons/copilot.svg +1 -0
  131. package/style/icons/copy.svg +1 -0
  132. package/style/icons/openai.svg +1 -0
  133. package/style/icons/opencode.svg +1 -0
  134. package/style/icons/sparkles-warning.svg +5 -0
  135. package/style/icons/sparkles.svg +1 -0
  136. package/style/index.css +1 -0
  137. package/style/index.js +1 -0
@@ -0,0 +1,127 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+ import React, { useEffect, useRef, useState } from 'react';
3
+ import { VscCheck, VscClose, VscCopy, VscHistory } from '../icons';
4
+ import { NBIAPI } from '../api';
5
+ import { buildResumeCommand, writeTextToClipboard } from '../utils';
6
+ function formatTimestamp(epochSeconds) {
7
+ if (!epochSeconds) {
8
+ return '';
9
+ }
10
+ const date = new Date(epochSeconds * 1000);
11
+ if (Number.isNaN(date.getTime())) {
12
+ return '';
13
+ }
14
+ return date.toLocaleString();
15
+ }
16
+ const COPY_LABELS = {
17
+ idle: 'Copy resume command',
18
+ copied: 'Resume command copied',
19
+ failed: 'Failed to copy resume command'
20
+ };
21
+ export function ClaudeSessionPicker(props) {
22
+ const [sessions, setSessions] = useState([]);
23
+ const [currentCwd, setCurrentCwd] = useState('');
24
+ const [loading, setLoading] = useState(true);
25
+ const [resuming, setResuming] = useState(false);
26
+ const [error, setError] = useState('');
27
+ const [copyFeedback, setCopyFeedback] = useState(null);
28
+ const copyTimerRef = useRef(null);
29
+ useEffect(() => {
30
+ return () => {
31
+ if (copyTimerRef.current !== null) {
32
+ clearTimeout(copyTimerRef.current);
33
+ }
34
+ };
35
+ }, []);
36
+ useEffect(() => {
37
+ var _a;
38
+ let cancelled = false;
39
+ const fetch = (_a = props.fetchSessions) !== null && _a !== void 0 ? _a : (() => NBIAPI.listClaudeSessions('cwd'));
40
+ fetch()
41
+ .then(result => {
42
+ if (cancelled) {
43
+ return;
44
+ }
45
+ setSessions(result.sessions);
46
+ setCurrentCwd(result.currentCwd);
47
+ setLoading(false);
48
+ })
49
+ .catch(reason => {
50
+ var _a, _b;
51
+ if (cancelled) {
52
+ return;
53
+ }
54
+ setError(String((_b = (_a = reason === null || reason === void 0 ? void 0 : reason.message) !== null && _a !== void 0 ? _a : reason) !== null && _b !== void 0 ? _b : 'Unknown error'));
55
+ setLoading(false);
56
+ });
57
+ return () => {
58
+ cancelled = true;
59
+ };
60
+ }, []);
61
+ const handleCopyResumeCommand = async (event, session) => {
62
+ event.stopPropagation();
63
+ event.preventDefault();
64
+ const ok = await writeTextToClipboard(buildResumeCommand(currentCwd, session.session_id));
65
+ setCopyFeedback({
66
+ sessionId: session.session_id,
67
+ status: ok ? 'copied' : 'failed'
68
+ });
69
+ if (copyTimerRef.current !== null) {
70
+ clearTimeout(copyTimerRef.current);
71
+ }
72
+ copyTimerRef.current = setTimeout(() => {
73
+ setCopyFeedback(null);
74
+ copyTimerRef.current = null;
75
+ }, 1500);
76
+ };
77
+ const handleResume = async (session) => {
78
+ var _a, _b;
79
+ if (resuming) {
80
+ return;
81
+ }
82
+ setResuming(true);
83
+ // When a custom fetchSessions is provided the caller owns the resume
84
+ // lifecycle (e.g. the launcher tile opens a terminal directly), so skip
85
+ // the NBI sidebar API call which requires Claude Code mode to be active.
86
+ if (props.fetchSessions) {
87
+ props.onResume(session);
88
+ return;
89
+ }
90
+ try {
91
+ await NBIAPI.resumeClaudeSession(session.session_id);
92
+ props.onResume(session);
93
+ }
94
+ catch (reason) {
95
+ setError(String((_b = (_a = reason === null || reason === void 0 ? void 0 : reason.message) !== null && _a !== void 0 ? _a : reason) !== null && _b !== void 0 ? _b : 'Unknown error'));
96
+ setResuming(false);
97
+ }
98
+ };
99
+ return (React.createElement("div", { className: "workspace-file-popover claude-session-picker", tabIndex: 1, autoFocus: true, onKeyDown: (event) => {
100
+ if (event.key === 'Escape') {
101
+ event.stopPropagation();
102
+ event.preventDefault();
103
+ props.onClose();
104
+ }
105
+ } },
106
+ React.createElement("div", { className: "mode-tools-popover-header" },
107
+ React.createElement("div", { className: "mode-tools-popover-header-icon" },
108
+ React.createElement(VscHistory, null)),
109
+ React.createElement("div", { className: "mode-tools-popover-title" }, "Resume Claude session"),
110
+ React.createElement("div", { style: { flexGrow: 1 } }),
111
+ React.createElement("div", { className: "mode-tools-popover-button mode-tools-popover-close-button", title: "Close", onClick: props.onClose },
112
+ React.createElement(VscClose, null))),
113
+ React.createElement("div", { className: "workspace-file-popover-body" },
114
+ error && (React.createElement("div", { className: "workspace-file-popover-status error" }, error)),
115
+ loading ? (React.createElement("div", { className: "workspace-file-popover-status" }, "Loading sessions\u2026")) : sessions.length === 0 ? (React.createElement("div", { className: "workspace-file-popover-status" }, "No previous Claude sessions found for this working directory.")) : (React.createElement("ul", { className: "claude-session-picker-list" }, sessions.map(session => {
116
+ const feedback = copyFeedback && copyFeedback.sessionId === session.session_id
117
+ ? copyFeedback.status
118
+ : null;
119
+ const buttonLabel = COPY_LABELS[feedback !== null && feedback !== void 0 ? feedback : 'idle'];
120
+ return (React.createElement("li", { key: session.session_id, className: `claude-session-picker-item${resuming ? ' busy' : ''}`, onClick: () => handleResume(session) },
121
+ session.preview && (React.createElement("div", { className: "claude-session-picker-item-preview" }, session.preview)),
122
+ React.createElement("div", { className: "claude-session-picker-item-meta" },
123
+ React.createElement("span", null, formatTimestamp(session.modified_at)),
124
+ React.createElement("span", { className: "claude-session-picker-item-id", title: session.session_id }, session.session_id.slice(0, 8)),
125
+ React.createElement("button", { type: "button", className: `claude-session-picker-item-copy${feedback ? ` ${feedback}` : ''}`, title: buttonLabel, "aria-label": buttonLabel, onClick: event => handleCopyResumeCommand(event, session) }, feedback === 'copied' ? React.createElement(VscCheck, null) : React.createElement(VscCopy, null)))));
126
+ }))))));
127
+ }
@@ -0,0 +1,25 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * Modal-form shell shared by the simple add/install dialogs across the
4
+ * Claude-MCP and Plugins panels. Owns:
5
+ * * backdrop + card layout (cancel-on-backdrop-click)
6
+ * * title / body / actions slots
7
+ * * Escape-to-cancel keyboard handler
8
+ * * inline error rendering when ``error`` is non-null
9
+ * * primary button label transitions for the submitting state
10
+ *
11
+ * Multi-step flows (e.g. the GitHub-import preview-then-install dialog in
12
+ * ``skills-panel.tsx``) keep their own shell since fitting them here
13
+ * would bloat the abstraction.
14
+ */
15
+ export declare function FormDialog(props: {
16
+ title: string;
17
+ submitLabel: string;
18
+ submitInProgressLabel?: string;
19
+ canSubmit: boolean;
20
+ submitting: boolean;
21
+ error?: string | null;
22
+ onCancel: () => void;
23
+ onSubmit: () => void;
24
+ children: ReactNode;
25
+ }): JSX.Element;
@@ -0,0 +1,35 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+ import React from 'react';
3
+ /**
4
+ * Modal-form shell shared by the simple add/install dialogs across the
5
+ * Claude-MCP and Plugins panels. Owns:
6
+ * * backdrop + card layout (cancel-on-backdrop-click)
7
+ * * title / body / actions slots
8
+ * * Escape-to-cancel keyboard handler
9
+ * * inline error rendering when ``error`` is non-null
10
+ * * primary button label transitions for the submitting state
11
+ *
12
+ * Multi-step flows (e.g. the GitHub-import preview-then-install dialog in
13
+ * ``skills-panel.tsx``) keep their own shell since fitting them here
14
+ * would bloat the abstraction.
15
+ */
16
+ export function FormDialog(props) {
17
+ var _a;
18
+ return (React.createElement("div", { className: "nbi-modal-backdrop", onClick: props.onCancel },
19
+ React.createElement("div", { className: "nbi-modal-card", role: "dialog", "aria-modal": "true", onClick: e => e.stopPropagation(), onKeyDown: e => {
20
+ if (e.key === 'Escape' && !props.submitting) {
21
+ props.onCancel();
22
+ }
23
+ }, tabIndex: -1 },
24
+ React.createElement("div", { className: "nbi-modal-title" }, props.title),
25
+ React.createElement("div", { className: "nbi-modal-body" },
26
+ props.children,
27
+ props.error && (React.createElement("div", { className: "nbi-skills-error", role: "alert" }, props.error))),
28
+ React.createElement("div", { className: "nbi-modal-actions" },
29
+ React.createElement("button", { className: "jp-Dialog-button jp-mod-reject jp-mod-styled", onClick: props.onCancel, disabled: props.submitting },
30
+ React.createElement("div", { className: "jp-Dialog-buttonLabel" }, "Cancel")),
31
+ React.createElement("button", { className: "jp-Dialog-button jp-mod-accept jp-mod-styled", onClick: props.onSubmit, disabled: !props.canSubmit },
32
+ React.createElement("div", { className: "jp-Dialog-buttonLabel" }, props.submitting
33
+ ? ((_a = props.submitInProgressLabel) !== null && _a !== void 0 ? _a : `${props.submitLabel}…`)
34
+ : props.submitLabel))))));
35
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ import { IClaudeSessionInfo } from '../api';
3
+ export interface ILauncherPickerProps {
4
+ onSessionSelected: (session: IClaudeSessionInfo) => void;
5
+ }
6
+ export declare function LauncherPicker({ onSessionSelected }: ILauncherPickerProps): JSX.Element;
@@ -0,0 +1,135 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+ import React, { useEffect, useRef, useState } from 'react';
3
+ import { NBIAPI } from '../api';
4
+ // Pick a short, glanceable label for a session's project. The basename
5
+ // of the cwd is usually the project's actual name; the full path stays
6
+ // available via the row's `title` attribute on hover.
7
+ function projectLabel(cwd) {
8
+ if (!cwd) {
9
+ return '';
10
+ }
11
+ const trimmed = cwd.replace(/\/+$/, '');
12
+ const idx = trimmed.lastIndexOf('/');
13
+ return idx >= 0 ? trimmed.slice(idx + 1) : trimmed;
14
+ }
15
+ export function LauncherPicker({ onSessionSelected }) {
16
+ const [sessions, setSessions] = useState([]);
17
+ const [loading, setLoading] = useState(true);
18
+ const [error, setError] = useState('');
19
+ const [filter, setFilter] = useState('');
20
+ const [highlightedIndex, setHighlightedIndex] = useState(-1);
21
+ const containerRef = useRef(null);
22
+ const listRef = useRef(null);
23
+ useEffect(() => {
24
+ NBIAPI.listClaudeSessions('all')
25
+ .then(result => {
26
+ setSessions(result.sessions);
27
+ setLoading(false);
28
+ })
29
+ .catch((reason) => {
30
+ var _a, _b;
31
+ setError(String((_b = (_a = reason === null || reason === void 0 ? void 0 : reason.message) !== null && _a !== void 0 ? _a : reason) !== null && _b !== void 0 ? _b : 'Unknown error'));
32
+ setLoading(false);
33
+ });
34
+ }, []);
35
+ const needle = filter.toLowerCase();
36
+ const filtered = filter
37
+ ? sessions.filter(s => {
38
+ var _a, _b;
39
+ return ((_a = s.preview) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(needle)) ||
40
+ ((_b = s.cwd) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes(needle));
41
+ })
42
+ : sessions;
43
+ // A held-over index against a refetched session set could silently
44
+ // point at a different session, so reset on any sessions change —
45
+ // not just length, which would miss equal-length-but-different sets.
46
+ useEffect(() => {
47
+ setHighlightedIndex(-1);
48
+ }, [filter, sessions]);
49
+ useEffect(() => {
50
+ if (highlightedIndex < 0 || !listRef.current) {
51
+ return;
52
+ }
53
+ const row = listRef.current.children[highlightedIndex];
54
+ row === null || row === void 0 ? void 0 : row.scrollIntoView({ block: 'nearest' });
55
+ }, [highlightedIndex]);
56
+ // Refs so the document-level keydown listener installed below can read
57
+ // the latest values without re-attaching on every render.
58
+ const filteredRef = useRef(filtered);
59
+ const highlightedIndexRef = useRef(highlightedIndex);
60
+ const onSessionSelectedRef = useRef(onSessionSelected);
61
+ filteredRef.current = filtered;
62
+ highlightedIndexRef.current = highlightedIndex;
63
+ onSessionSelectedRef.current = onSessionSelected;
64
+ // Lumino's Dialog catches Enter at capture phase on the dialog node and
65
+ // triggers its default OK button (the "New Session" button), so a React
66
+ // bubble-phase handler never sees Enter inside the picker. Attach a
67
+ // document-capture listener here so we beat the dialog and activate the
68
+ // highlighted row instead — falling through to the dialog's New Session
69
+ // path only when there's nothing selectable to land on.
70
+ useEffect(() => {
71
+ const handler = (e) => {
72
+ if (e.key !== 'Enter') {
73
+ return;
74
+ }
75
+ const node = containerRef.current;
76
+ if (!node || !node.contains(e.target)) {
77
+ return;
78
+ }
79
+ const list = filteredRef.current;
80
+ if (list.length === 0) {
81
+ return;
82
+ }
83
+ e.preventDefault();
84
+ e.stopImmediatePropagation();
85
+ const idx = highlightedIndexRef.current;
86
+ onSessionSelectedRef.current(list[idx >= 0 ? idx : 0]);
87
+ };
88
+ document.addEventListener('keydown', handler, { capture: true });
89
+ return () => document.removeEventListener('keydown', handler, { capture: true });
90
+ }, []);
91
+ const handleKeyDown = (e) => {
92
+ if (filtered.length === 0) {
93
+ return;
94
+ }
95
+ // From "no row highlighted" (-1), ArrowDown jumps to the first row
96
+ // and ArrowUp jumps to the last — each direction lands at its
97
+ // nearest end so the user always reaches a valid row in one press.
98
+ if (e.key === 'ArrowDown') {
99
+ e.preventDefault();
100
+ setHighlightedIndex(i => (i < 0 || i >= filtered.length - 1 ? 0 : i + 1));
101
+ }
102
+ else if (e.key === 'ArrowUp') {
103
+ e.preventDefault();
104
+ setHighlightedIndex(i => (i <= 0 ? filtered.length - 1 : i - 1));
105
+ }
106
+ };
107
+ if (loading) {
108
+ return (React.createElement("div", { className: "nbi-claude-code-picker-status" }, "Loading sessions\u2026"));
109
+ }
110
+ if (error) {
111
+ return (React.createElement("div", { className: "nbi-claude-code-picker-status nbi-claude-code-picker-error" }, error));
112
+ }
113
+ const activeRowId = highlightedIndex >= 0
114
+ ? `nbi-claude-session-row-${filtered[highlightedIndex].session_id}`
115
+ : undefined;
116
+ return (React.createElement("div", { className: "nbi-claude-code-picker-body", ref: containerRef, onKeyDown: handleKeyDown },
117
+ React.createElement("input", { className: "nbi-claude-code-picker-search", type: "text", placeholder: "Filter sessions...", value: filter, onChange: (e) => setFilter(e.target.value), autoFocus: true, role: "combobox", "aria-expanded": filtered.length > 0, "aria-controls": "nbi-claude-session-listbox", "aria-activedescendant": activeRowId }),
118
+ React.createElement("div", { className: "nbi-claude-code-picker-list", id: "nbi-claude-session-listbox", role: "listbox", ref: listRef }, filtered.length === 0 ? (React.createElement("div", { className: "nbi-claude-code-picker-empty" }, filter
119
+ ? 'No sessions match your filter.'
120
+ : 'No previous sessions found.')) : (filtered.map((session, index) => {
121
+ const isHighlighted = index === highlightedIndex;
122
+ return (React.createElement("div", { key: session.session_id, id: `nbi-claude-session-row-${session.session_id}`, role: "option", className: 'nbi-claude-code-picker-session' +
123
+ (isHighlighted ? ' highlighted' : ''), tabIndex: 0, "aria-selected": isHighlighted, onClick: () => onSessionSelected(session), onFocus: () => setHighlightedIndex(index) },
124
+ React.createElement("div", { className: "nbi-claude-code-picker-session-top" },
125
+ React.createElement("span", { className: "nbi-claude-code-picker-session-id" }, session.session_id.slice(0, 8)),
126
+ (() => {
127
+ var _a;
128
+ const full = (_a = session.cwd) !== null && _a !== void 0 ? _a : '';
129
+ const label = projectLabel(full);
130
+ const fullDiffersFromLabel = full && full !== label;
131
+ return (React.createElement("span", { className: "nbi-claude-code-picker-session-project", title: full, "aria-label": fullDiffersFromLabel ? full : undefined }, label));
132
+ })()),
133
+ session.preview && (React.createElement("div", { className: "nbi-claude-code-picker-msg" }, session.preview))));
134
+ })))));
135
+ }
@@ -0,0 +1,2 @@
1
+ export declare function mcpServerSettingsToEnabledState(mcpServers: any, mcpServerSettings: any): Map<string, Set<string>>;
2
+ export declare function mcpServerSettingsToServerToolEnabledState(mcpServers: any, mcpServerSettings: any, serverId: string): Set<string>;
@@ -0,0 +1,37 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+ export function mcpServerSettingsToEnabledState(mcpServers, mcpServerSettings) {
3
+ const mcpServerEnabledState = new Map();
4
+ for (const server of mcpServers) {
5
+ const mcpServerToolEnabledState = mcpServerSettingsToServerToolEnabledState(mcpServers, mcpServerSettings, server.id);
6
+ if (mcpServerToolEnabledState) {
7
+ mcpServerEnabledState.set(server.id, mcpServerToolEnabledState);
8
+ }
9
+ }
10
+ return mcpServerEnabledState;
11
+ }
12
+ export function mcpServerSettingsToServerToolEnabledState(mcpServers, mcpServerSettings, serverId) {
13
+ var _a;
14
+ const server = mcpServers.find((server) => server.id === serverId);
15
+ let mcpServerToolEnabledState = null;
16
+ if (!server) {
17
+ return mcpServerToolEnabledState;
18
+ }
19
+ if (mcpServerSettings[server.id]) {
20
+ const serverSettings = mcpServerSettings[server.id];
21
+ if (!serverSettings.disabled) {
22
+ mcpServerToolEnabledState = new Set();
23
+ for (const tool of server.tools) {
24
+ if (!((_a = serverSettings.disabled_tools) === null || _a === void 0 ? void 0 : _a.includes(tool.name))) {
25
+ mcpServerToolEnabledState.add(tool.name);
26
+ }
27
+ }
28
+ }
29
+ }
30
+ else {
31
+ mcpServerToolEnabledState = new Set();
32
+ for (const tool of server.tools) {
33
+ mcpServerToolEnabledState.add(tool.name);
34
+ }
35
+ }
36
+ return mcpServerToolEnabledState;
37
+ }
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ export interface INotebookGenerationPopoverProps {
3
+ initialShowInChat?: boolean;
4
+ onSubmit: (prompt: string, showInChat: boolean) => void;
5
+ onClose: () => void;
6
+ }
7
+ export declare function NotebookGenerationPopover(props: INotebookGenerationPopoverProps): JSX.Element;
@@ -0,0 +1,60 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+ import React, { useEffect, useRef, useState } from 'react';
3
+ import { VscClose, VscSend, VscSparkle } from '../icons';
4
+ import { CheckBoxItem } from './checkbox';
5
+ export function NotebookGenerationPopover(props) {
6
+ var _a;
7
+ const [prompt, setPrompt] = useState('');
8
+ const [showInChat, setShowInChat] = useState((_a = props.initialShowInChat) !== null && _a !== void 0 ? _a : true);
9
+ const textareaRef = useRef(null);
10
+ useEffect(() => {
11
+ // Defer to the next frame so the focus call lands after Lumino's
12
+ // attach lifecycle and JupyterLab's focus tracker have settled —
13
+ // otherwise the active notebook can win the focus race and the
14
+ // textarea stays unfocused (issue #231).
15
+ const handle = window.requestAnimationFrame(() => {
16
+ var _a;
17
+ (_a = textareaRef.current) === null || _a === void 0 ? void 0 : _a.focus();
18
+ });
19
+ return () => window.cancelAnimationFrame(handle);
20
+ }, []);
21
+ const trimmed = prompt.trim();
22
+ const canSubmit = trimmed.length > 0;
23
+ const handleSubmit = () => {
24
+ if (!canSubmit) {
25
+ return;
26
+ }
27
+ props.onSubmit(trimmed, showInChat);
28
+ };
29
+ const handleKeyDown = (event) => {
30
+ if (event.key === 'Escape') {
31
+ event.stopPropagation();
32
+ event.preventDefault();
33
+ props.onClose();
34
+ return;
35
+ }
36
+ };
37
+ const handleTextareaKeyDown = (event) => {
38
+ if (event.key === 'Enter' && !event.shiftKey) {
39
+ event.preventDefault();
40
+ handleSubmit();
41
+ }
42
+ };
43
+ return (React.createElement("div", { className: "notebook-generation-popover", tabIndex: -1, onKeyDown: handleKeyDown },
44
+ React.createElement("div", { className: "notebook-generation-popover-header" },
45
+ React.createElement("div", { className: "notebook-generation-popover-header-icon" },
46
+ React.createElement(VscSparkle, null)),
47
+ React.createElement("div", { className: "notebook-generation-popover-title" }, "Update active notebook"),
48
+ React.createElement("div", { style: { flexGrow: 1 } }),
49
+ React.createElement("button", { type: "button", className: "notebook-generation-popover-close-button", "aria-label": "Close notebook generation popover", title: "Close", onClick: props.onClose },
50
+ React.createElement(VscClose, { "aria-hidden": "true" }))),
51
+ React.createElement("div", { className: "notebook-generation-popover-body" },
52
+ React.createElement("textarea", { ref: textareaRef, className: "notebook-generation-popover-input", rows: 4, placeholder: "Describe how to update the active notebook...", value: prompt, onChange: (event) => setPrompt(event.target.value), onKeyDown: handleTextareaKeyDown }),
53
+ React.createElement(CheckBoxItem, { checked: showInChat, label: "Show in chat", tooltip: 'When enabled, the prompt opens the Notebook Intelligence ' +
54
+ 'chat sidebar. Disable to keep the chat hidden and only ' +
55
+ 'show progress on the notebook toolbar.', onClick: () => setShowInChat(value => !value) }),
56
+ React.createElement("div", { className: "notebook-generation-popover-actions" },
57
+ React.createElement("button", { type: "button", className: "notebook-generation-popover-submit", disabled: !canSubmit, onClick: handleSubmit, title: "Generate (Enter)" },
58
+ React.createElement(VscSend, null),
59
+ React.createElement("span", null, "Generate"))))));
60
+ }
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare function PillItem(props: any): React.JSX.Element;
@@ -0,0 +1,5 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+ import React from 'react';
3
+ export function PillItem(props) {
4
+ return (React.createElement("div", { className: `pill-item ${props.checked ? 'checked' : ''}`, title: props.title, onClick: event => props.onClick(event) }, props.label));
5
+ }
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ export declare function summarizePluginNames(names: readonly string[] | undefined, visible: number): string;
3
+ export declare function SettingsPanelComponentPlugins(_props: any): JSX.Element;