@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,382 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+
3
+ import { Notification } from '@jupyterlab/apputils';
4
+ import { Widget } from '@lumino/widgets';
5
+
6
+ import { NBIAPI } from './api';
7
+ import { DragMode, formatForMode, invertMode } from './terminal-drag-format';
8
+
9
+ export type { DragMode } from './terminal-drag-format';
10
+ export { formatForMode, invertMode } from './terminal-drag-format';
11
+
12
+ // Structural types over `IMainAreaWidgetLike` and
13
+ // `ITerminalTracker`: @jupyterlab/terminal nests its own copies of
14
+ // @jupyterlab/apputils and @lumino/widgets, so the nominal types don't
15
+ // unify with our top-level ones. Capturing only what we touch keeps the
16
+ // module decoupled from that version skew and unit-testable without a
17
+ // real JupyterLab application context.
18
+ interface ITerminalWidgetLike {
19
+ paste(text: string): void;
20
+ activate?(): void;
21
+ }
22
+
23
+ interface IDisposedSignalLike {
24
+ connect(slot: () => void): void;
25
+ }
26
+
27
+ interface ITerminalToolbarLike {
28
+ addItem(name: string, widget: Widget): boolean;
29
+ }
30
+
31
+ interface IMainAreaWidgetLike {
32
+ node: HTMLElement;
33
+ content: ITerminalWidgetLike;
34
+ toolbar: ITerminalToolbarLike;
35
+ disposed: IDisposedSignalLike;
36
+ isDisposed?: boolean;
37
+ activate?(): void;
38
+ }
39
+
40
+ interface ITerminalTrackerLike {
41
+ widgetAdded: {
42
+ connect(slot: (sender: unknown, widget: IMainAreaWidgetLike) => void): void;
43
+ };
44
+ forEach(fn: (widget: IMainAreaWidgetLike) => void): void;
45
+ }
46
+
47
+ // File-browser drag dispatches a Lumino lm-drop event carrying paths
48
+ // under this MIME (see node_modules/@jupyterlab/filebrowser/lib/listing.js).
49
+ const FILE_BROWSER_MIME = 'application/x-jupyter-icontents';
50
+
51
+ const DRAG_OVER_CLASS = 'nbi-terminal-drag-over';
52
+ const TOOLBAR_BUTTON_CLASS = 'nbi-terminal-drag-mode-button';
53
+
54
+ interface ITerminalDragState {
55
+ mode: DragMode;
56
+ dragDepth: number;
57
+ cleanup: () => void;
58
+ }
59
+
60
+ const widgetState = new WeakMap<IMainAreaWidgetLike, ITerminalDragState>();
61
+
62
+ export interface ITerminalDragOptions {
63
+ // Untyped on the public surface because @jupyterlab/terminal nests its
64
+ // own copy of every Lumino/JL type; coercing inside keeps callers from
65
+ // needing to know about the duplication.
66
+ tracker: unknown;
67
+ /**
68
+ * Re-evaluated on each event so flipping the admin policy at runtime
69
+ * (e.g. force-off via env at next reload) takes effect on listeners
70
+ * that are already wired without needing to tear them down.
71
+ */
72
+ isEnabled: () => boolean;
73
+ }
74
+
75
+ export function attachTerminalDragDrop(options: ITerminalDragOptions): void {
76
+ const tracker = options.tracker as ITerminalTrackerLike;
77
+ const { isEnabled } = options;
78
+
79
+ const wire = (widget: IMainAreaWidgetLike) => {
80
+ if (widgetState.has(widget)) {
81
+ return;
82
+ }
83
+ setupTerminal(widget, isEnabled);
84
+ };
85
+
86
+ tracker.forEach(wire);
87
+ tracker.widgetAdded.connect((_, widget) => wire(widget));
88
+ }
89
+
90
+ function setupTerminal(
91
+ widget: IMainAreaWidgetLike,
92
+ isEnabled: () => boolean
93
+ ): void {
94
+ const host = widget.node;
95
+
96
+ const state: ITerminalDragState = {
97
+ mode: 'mention',
98
+ dragDepth: 0,
99
+ cleanup: () => {}
100
+ };
101
+
102
+ const inject = (paths: string[], shiftHeld: boolean) => {
103
+ if (paths.length === 0) {
104
+ return;
105
+ }
106
+ // Async upload paths can finish after the terminal is closed; calling
107
+ // paste on a disposed Lumino Widget throws.
108
+ if (widget.isDisposed) {
109
+ return;
110
+ }
111
+ const effectiveMode = invertMode(state.mode, shiftHeld);
112
+ widget.content.paste(`${formatForMode(paths, effectiveMode)} `);
113
+ // Activate the outer MainAreaWidget so the terminal also gets raised
114
+ // if it's a background tab in a split. Otherwise the next keystroke
115
+ // goes to the file-browser (Enter would "open the selected file") or
116
+ // to whichever surface held focus before the drag.
117
+ widget.activate?.();
118
+ };
119
+
120
+ const handleDragEnter = (event: DragEvent) => {
121
+ if (!isEnabled() || !event.dataTransfer) {
122
+ return;
123
+ }
124
+ if (!event.dataTransfer.types.includes('Files')) {
125
+ return;
126
+ }
127
+ state.dragDepth += 1;
128
+ host.classList.add(DRAG_OVER_CLASS);
129
+ event.preventDefault();
130
+ event.stopImmediatePropagation();
131
+ };
132
+
133
+ const handleDragOver = (event: DragEvent) => {
134
+ if (!isEnabled() || !event.dataTransfer) {
135
+ return;
136
+ }
137
+ if (!event.dataTransfer.types.includes('Files')) {
138
+ return;
139
+ }
140
+ event.preventDefault();
141
+ event.stopImmediatePropagation();
142
+ event.dataTransfer.dropEffect = 'copy';
143
+ };
144
+
145
+ const handleDragLeave = (event: DragEvent) => {
146
+ if (!isEnabled()) {
147
+ return;
148
+ }
149
+ state.dragDepth = Math.max(0, state.dragDepth - 1);
150
+ if (state.dragDepth === 0) {
151
+ host.classList.remove(DRAG_OVER_CLASS);
152
+ }
153
+ event.preventDefault();
154
+ event.stopImmediatePropagation();
155
+ };
156
+
157
+ const handleDrop = (event: DragEvent) => {
158
+ if (!isEnabled()) {
159
+ return;
160
+ }
161
+ state.dragDepth = 0;
162
+ host.classList.remove(DRAG_OVER_CLASS);
163
+ if (!event.dataTransfer) {
164
+ return;
165
+ }
166
+ const files = Array.from(event.dataTransfer.files);
167
+ if (files.length === 0) {
168
+ return;
169
+ }
170
+ event.preventDefault();
171
+ event.stopImmediatePropagation();
172
+ const shiftHeld = event.shiftKey;
173
+ void uploadAndInject(files, shiftHeld, inject);
174
+ };
175
+
176
+ // Lumino dispatches lm-* events on the deepest DOM element under the
177
+ // cursor. Listening on `host` would in theory catch the bubble, but
178
+ // intermediate widgets (e.g. xterm's viewport) can call
179
+ // stopPropagation in a target-phase handler before we see it. Listening
180
+ // at the document level with a containment check is the most reliable
181
+ // way to observe a drop that's geometrically inside this terminal.
182
+ const isInsideHost = (event: Event): boolean => {
183
+ const target = event.target;
184
+ return target instanceof Node && host.contains(target);
185
+ };
186
+
187
+ const handleLuminoDragEnter = (event: Event) => {
188
+ if (!isEnabled() || !hasFileBrowserPaths(event) || !isInsideHost(event)) {
189
+ return;
190
+ }
191
+ state.dragDepth += 1;
192
+ host.classList.add(DRAG_OVER_CLASS);
193
+ event.preventDefault();
194
+ event.stopPropagation();
195
+ };
196
+
197
+ const handleLuminoDragOver = (event: Event) => {
198
+ if (!isEnabled() || !hasFileBrowserPaths(event) || !isInsideHost(event)) {
199
+ return;
200
+ }
201
+ event.preventDefault();
202
+ event.stopPropagation();
203
+ // Echo the source's proposedAction back as dropAction. The file
204
+ // browser starts its Drag with supportedActions: 'move', so a
205
+ // hardcoded 'copy' falls through validateAction to 'none' and
206
+ // Lumino skips lm-drop on pointerup. Mirroring proposedAction keeps
207
+ // us inside whatever the source supports.
208
+ const dragEvent = event as unknown as {
209
+ proposedAction?: string;
210
+ dropAction: string;
211
+ };
212
+ dragEvent.dropAction = dragEvent.proposedAction || 'move';
213
+ };
214
+
215
+ const handleLuminoDragLeave = (event: Event) => {
216
+ if (!isEnabled() || !isInsideHost(event)) {
217
+ return;
218
+ }
219
+ state.dragDepth = Math.max(0, state.dragDepth - 1);
220
+ if (state.dragDepth === 0) {
221
+ host.classList.remove(DRAG_OVER_CLASS);
222
+ }
223
+ event.preventDefault();
224
+ event.stopPropagation();
225
+ };
226
+
227
+ const handleLuminoDrop = (event: Event) => {
228
+ if (!isEnabled() || !hasFileBrowserPaths(event) || !isInsideHost(event)) {
229
+ return;
230
+ }
231
+ const dragEvent = event as unknown as {
232
+ mimeData: { getData: (key: string) => unknown };
233
+ shiftKey: boolean;
234
+ proposedAction?: string;
235
+ dropAction: string;
236
+ };
237
+ const paths = dragEvent.mimeData.getData(FILE_BROWSER_MIME);
238
+ if (!Array.isArray(paths) || paths.length === 0) {
239
+ return;
240
+ }
241
+ event.preventDefault();
242
+ event.stopPropagation();
243
+ dragEvent.dropAction = dragEvent.proposedAction || 'move';
244
+ state.dragDepth = 0;
245
+ host.classList.remove(DRAG_OVER_CLASS);
246
+ inject(
247
+ paths.filter((p): p is string => typeof p === 'string'),
248
+ dragEvent.shiftKey
249
+ );
250
+ };
251
+
252
+ host.addEventListener('dragenter', handleDragEnter, true);
253
+ host.addEventListener('dragover', handleDragOver, true);
254
+ host.addEventListener('dragleave', handleDragLeave, true);
255
+ host.addEventListener('drop', handleDrop, true);
256
+ // lm-* listeners go on the document (capture phase) so we observe
257
+ // them before any intermediate widget can stopPropagation. The
258
+ // containment check filters to events whose target is inside this
259
+ // terminal's host node.
260
+ document.addEventListener('lm-dragenter', handleLuminoDragEnter, true);
261
+ document.addEventListener('lm-dragover', handleLuminoDragOver, true);
262
+ document.addEventListener('lm-dragleave', handleLuminoDragLeave, true);
263
+ document.addEventListener('lm-drop', handleLuminoDrop, true);
264
+
265
+ const button = new TerminalDragModeButton('mention', () => {
266
+ state.mode = state.mode === 'mention' ? 'raw' : 'mention';
267
+ button.setMode(state.mode);
268
+ });
269
+ widget.toolbar.addItem('nbi-terminal-drag-mode', button);
270
+
271
+ state.cleanup = () => {
272
+ host.removeEventListener('dragenter', handleDragEnter, true);
273
+ host.removeEventListener('dragover', handleDragOver, true);
274
+ host.removeEventListener('dragleave', handleDragLeave, true);
275
+ host.removeEventListener('drop', handleDrop, true);
276
+ document.removeEventListener('lm-dragenter', handleLuminoDragEnter, true);
277
+ document.removeEventListener('lm-dragover', handleLuminoDragOver, true);
278
+ document.removeEventListener('lm-dragleave', handleLuminoDragLeave, true);
279
+ document.removeEventListener('lm-drop', handleLuminoDrop, true);
280
+ };
281
+
282
+ widget.disposed.connect(() => {
283
+ state.cleanup();
284
+ widgetState.delete(widget);
285
+ });
286
+
287
+ widgetState.set(widget, state);
288
+ }
289
+
290
+ function hasFileBrowserPaths(event: Event): boolean {
291
+ const mimeData = (
292
+ event as unknown as { mimeData?: { hasData?: (key: string) => boolean } }
293
+ ).mimeData;
294
+ return mimeData?.hasData?.(FILE_BROWSER_MIME) === true;
295
+ }
296
+
297
+ async function uploadAndInject(
298
+ files: File[],
299
+ shiftHeld: boolean,
300
+ inject: (paths: string[], shiftHeld: boolean) => void
301
+ ): Promise<void> {
302
+ const results = await Promise.allSettled(
303
+ files.map(f => NBIAPI.uploadFile(f))
304
+ );
305
+ const paths: string[] = [];
306
+ const failures: { name: string; reason: string }[] = [];
307
+ results.forEach((result, index) => {
308
+ const file = files[index];
309
+ if (result.status === 'fulfilled') {
310
+ paths.push(result.value.serverPath);
311
+ return;
312
+ }
313
+ failures.push({
314
+ name: file.name,
315
+ reason: describeUploadError(result.reason)
316
+ });
317
+ });
318
+ if (failures.length > 0) {
319
+ // Inline in the toast so the user sees both what failed and why
320
+ // (e.g. 413 from the size cap). Truncated to 3 entries; rest collapsed
321
+ // into a "+ N more" footer to fit JL's 140-char notification limit.
322
+ const head = failures
323
+ .slice(0, 3)
324
+ .map(f => `${f.name}: ${f.reason}`)
325
+ .join('; ');
326
+ const tail = failures.length > 3 ? ` (+${failures.length - 3} more)` : '';
327
+ Notification.error(`Terminal drop upload failed for ${head}${tail}`);
328
+ }
329
+ inject(paths, shiftHeld);
330
+ }
331
+
332
+ function describeUploadError(reason: unknown): string {
333
+ if (reason && typeof reason === 'object') {
334
+ const r = reason as { message?: unknown; response?: { status?: number } };
335
+ if (typeof r.message === 'string' && r.message.trim().length > 0) {
336
+ return r.message;
337
+ }
338
+ if (r.response && typeof r.response.status === 'number') {
339
+ return `HTTP ${r.response.status}`;
340
+ }
341
+ }
342
+ return String(reason);
343
+ }
344
+
345
+ class TerminalDragModeButton extends Widget {
346
+ private _button: HTMLButtonElement;
347
+ private _onToggle: () => void;
348
+
349
+ constructor(initialMode: DragMode, onToggle: () => void) {
350
+ super();
351
+ this.addClass('jp-Toolbar-item');
352
+ this.addClass(TOOLBAR_BUTTON_CLASS);
353
+ this._onToggle = onToggle;
354
+
355
+ this._button = document.createElement('button');
356
+ this._button.type = 'button';
357
+ this._button.classList.add('jp-ToolbarButtonComponent');
358
+ this._button.classList.add(`${TOOLBAR_BUTTON_CLASS}-toggle`);
359
+ this._button.addEventListener('click', () => this._onToggle());
360
+ this.node.appendChild(this._button);
361
+
362
+ this.setMode(initialMode);
363
+ }
364
+
365
+ setMode(mode: DragMode): void {
366
+ const isMention = mode === 'mention';
367
+ this._button.textContent = isMention ? '@' : '/';
368
+ this._button.setAttribute('aria-pressed', isMention ? 'false' : 'true');
369
+ // aria-label carries the full mode + Shift-modifier explanation;
370
+ // title is a short hover-tip so screen readers don't double-announce
371
+ // the same string from both attributes.
372
+ this._button.setAttribute(
373
+ 'aria-label',
374
+ isMention
375
+ ? 'Terminal drop inserts @-mention paths. Click to switch to raw path mode. Hold Shift while dropping to invert for one drop.'
376
+ : 'Terminal drop inserts raw, shell-escaped absolute paths. Click to switch to @-mention mode. Hold Shift while dropping to invert for one drop.'
377
+ );
378
+ this._button.title = isMention
379
+ ? 'Drop mode: @-mention'
380
+ : 'Drop mode: raw path';
381
+ }
382
+ }
package/src/tokens.ts ADDED
@@ -0,0 +1,171 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+
3
+ import { Widget } from '@lumino/widgets';
4
+ import { CodeEditor } from '@jupyterlab/codeeditor';
5
+ import { Token } from '@lumino/coreutils';
6
+
7
+ export interface IActiveDocumentInfo {
8
+ activeWidget: Widget | null;
9
+ language: string;
10
+ filename: string;
11
+ filePath: string;
12
+ activeCellIndex: number;
13
+ selection?: CodeEditor.IRange;
14
+ }
15
+
16
+ export interface IChatCompletionResponseEmitter {
17
+ emit: (response: any) => void;
18
+ }
19
+
20
+ export enum RequestDataType {
21
+ ChatRequest = 'chat-request',
22
+ ChatUserInput = 'chat-user-input',
23
+ ClearChatHistory = 'clear-chat-history',
24
+ RunUICommandResponse = 'run-ui-command-response',
25
+ GenerateCode = 'generate-code',
26
+ CancelChatRequest = 'cancel-chat-request',
27
+ InlineCompletionRequest = 'inline-completion-request',
28
+ CancelInlineCompletionRequest = 'cancel-inline-completion-request'
29
+ }
30
+
31
+ export enum BackendMessageType {
32
+ StreamMessage = 'stream-message',
33
+ StreamEnd = 'stream-end',
34
+ RunUICommand = 'run-ui-command',
35
+ GitHubCopilotLoginStatusChange = 'github-copilot-login-status-change',
36
+ MCPServerStatusChange = 'mcp-server-status-change',
37
+ ClaudeCodeStatusChange = 'claude-code-status-change',
38
+ ClaudeCodeHeartbeat = 'claude-code-heartbeat',
39
+ SkillsReloaded = 'skills-reloaded'
40
+ }
41
+
42
+ export enum ResponseStreamDataType {
43
+ LLMRaw = 'llm-raw',
44
+ Markdown = 'markdown',
45
+ MarkdownPart = 'markdown-part',
46
+ Image = 'image',
47
+ HTMLFrame = 'html-frame',
48
+ Button = 'button',
49
+ Anchor = 'anchor',
50
+ Progress = 'progress',
51
+ Confirmation = 'confirmation',
52
+ AskUserQuestion = 'ask-user-question'
53
+ }
54
+
55
+ export enum ContextType {
56
+ Custom = 'custom',
57
+ CurrentFile = 'current-file',
58
+ OutputContext = 'output-context'
59
+ }
60
+
61
+ export interface IOutputContextItem {
62
+ cellSource: string;
63
+ mimeBundles: { mimeType: string; data: string; sizeTokens: number }[];
64
+ isError: boolean;
65
+ truncated: boolean;
66
+ }
67
+
68
+ export enum MCPServerStatus {
69
+ NotConnected = 'not-connected',
70
+ Connecting = 'connecting',
71
+ Disconnecting = 'disconnecting',
72
+ FailedToConnect = 'failed-to-connect',
73
+ Connected = 'connected',
74
+ UpdatingToolList = 'updating-tool-list',
75
+ UpdatedToolList = 'updated-tool-list',
76
+ UpdatingPromptList = 'updating-prompt-list',
77
+ UpdatedPromptList = 'updated-prompt-list'
78
+ }
79
+
80
+ export interface IContextItem {
81
+ type: ContextType;
82
+ content: string;
83
+ currentCellContents: ICellContents;
84
+ filePath?: string;
85
+ cellIndex?: number;
86
+ startLine?: number;
87
+ endLine?: number;
88
+ isImage?: boolean;
89
+ mimeType?: string;
90
+ outputContext?: IOutputContextItem;
91
+ }
92
+
93
+ export interface ICellContents {
94
+ input: string;
95
+ output: string;
96
+ }
97
+
98
+ export interface IChatParticipant {
99
+ id: string;
100
+ name: string;
101
+ description: string;
102
+ iconPath: string;
103
+ commands: string[];
104
+ }
105
+
106
+ export interface IToolSelections {
107
+ builtinToolsets?: string[];
108
+ mcpServers?: {
109
+ [key: string]: string[];
110
+ };
111
+ extensions?: {
112
+ [key: string]: string[];
113
+ };
114
+ }
115
+
116
+ export enum BuiltinToolsetType {
117
+ NotebookEdit = 'nbi-notebook-edit',
118
+ NotebookExecute = 'nbi-notebook-execute',
119
+ PythonFileEdit = 'nbi-python-file-edit',
120
+ FileEdit = 'nbi-file-edit',
121
+ FileRead = 'nbi-file-read',
122
+ CommandExecute = 'nbi-command-execute'
123
+ }
124
+
125
+ export const GITHUB_COPILOT_PROVIDER_ID = 'github-copilot';
126
+ export const CLAUDE_CODE_CHAT_PARTICIPANT_ID = 'claude-code';
127
+
128
+ export enum AssistantMode {
129
+ Default = 'default',
130
+ Claude = 'claude'
131
+ }
132
+
133
+ export enum TelemetryEventType {
134
+ InlineCompletionRequest = 'inline-completion-request',
135
+ ExplainThisRequest = 'explain-this-request',
136
+ FixThisCodeRequest = 'fix-this-code-request',
137
+ ExplainThisOutputRequest = 'explain-this-output-request',
138
+ TroubleshootThisOutputRequest = 'troubleshoot-this-output-request',
139
+ OutputFollowUpRequest = 'output-follow-up-request',
140
+ GenerateCodeRequest = 'generate-code-request',
141
+ ChatRequest = 'chat-request',
142
+ InlineChatRequest = 'inline-chat-request',
143
+ ChatResponse = 'chat-response',
144
+ InlineChatResponse = 'inline-chat-response',
145
+ InlineCompletionResponse = 'inline-completion-response',
146
+ Feedback = 'feedback'
147
+ }
148
+
149
+ export interface ITelemetryEvent {
150
+ type: TelemetryEventType;
151
+ data?: any;
152
+ }
153
+
154
+ export interface ITelemetryListener {
155
+ get name(): string;
156
+ onTelemetryEvent: (event: ITelemetryEvent) => void;
157
+ }
158
+
159
+ export interface ITelemetryEmitter {
160
+ emitTelemetryEvent(event: ITelemetryEvent): void;
161
+ }
162
+
163
+ export const INotebookIntelligence = new Token<INotebookIntelligence>(
164
+ '@plmbr/notebook-intelligence:INotebookIntelligence',
165
+ 'AI coding assistant for JupyterLab.'
166
+ );
167
+
168
+ export interface INotebookIntelligence {
169
+ registerTelemetryListener: (listener: ITelemetryListener) => void;
170
+ unregisterTelemetryListener: (listener: ITelemetryListener) => void;
171
+ }
@@ -0,0 +1,21 @@
1
+ // Copyright (c) Mehmet Bektas <mbektasgh@outlook.com>
2
+
3
+ /**
4
+ * Anchor-id constants shared between the tour step definitions and the
5
+ * chat-sidebar JSX. Centralising these keeps the two halves coupled at
6
+ * the TypeScript level rather than by string identity — a typo on
7
+ * either side now surfaces at compile time instead of silently
8
+ * skipping a step at runtime.
9
+ */
10
+ export const TOUR_ANCHOR = {
11
+ newChat: 'new-chat',
12
+ settingsGear: 'settings-gear',
13
+ claudeHistory: 'claude-history',
14
+ slashCommands: 'slash-commands',
15
+ addContext: 'add-context',
16
+ uploadFile: 'upload-file',
17
+ promptInput: 'prompt-input',
18
+ chatMode: 'chat-mode'
19
+ } as const;
20
+
21
+ export type TourAnchorId = (typeof TOUR_ANCHOR)[keyof typeof TOUR_ANCHOR];