jupyter-chat-components 0.1.3 → 0.3.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.
package/src/token.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import { IRenderMime } from '@jupyterlab/rendermime-interfaces';
2
2
 
3
+ import { TranslationBundle } from '@jupyterlab/translation';
4
+
3
5
  import { Token } from '@lumino/coreutils';
4
6
 
7
+ import * as React from 'react';
8
+
5
9
  /**
6
10
  * The token providing the chat components renderer.
7
11
  */
@@ -17,37 +21,167 @@ export type ToolCallApproval =
17
21
  | ((targetId: string, approvalId: string, approve: boolean) => void)
18
22
  | null;
19
23
 
24
+ /**
25
+ * The callback to remove a queued message.
26
+ */
27
+ export type RemoveQueuedMessage =
28
+ | ((targetId: string, messageId: string) => void)
29
+ | null;
30
+
20
31
  /**
21
32
  * The interface for components renderer factory.
22
33
  */
23
34
  export interface IComponentsRendererFactory
24
35
  extends IRenderMime.IRendererFactory {
36
+ /**
37
+ * The registry of React components available for rendering.
38
+ */
39
+ registry: IComponentRegistry;
40
+
25
41
  /**
26
42
  * The callback to approve or reject a tool.
27
43
  */
28
44
  toolCallApproval: ToolCallApproval;
45
+
46
+ /**
47
+ * The callback to remove a queued message.
48
+ */
49
+ removeQueuedMessage: RemoveQueuedMessage;
50
+ }
51
+
52
+ /**
53
+ * The interface for the component registry.
54
+ */
55
+ export interface IComponentRegistry {
56
+ /**
57
+ * Register a React component.
58
+ *
59
+ * @param name - The unique name/identifier for the component
60
+ * @param component - The React component
61
+ */
62
+ add(name: string, component: React.ComponentType<any>): void;
63
+
64
+ /**
65
+ * Get a registered component by name.
66
+ *
67
+ * @param name - The name of the component
68
+ * @returns The React component, or undefined if not found
69
+ */
70
+ get(name: string): React.ComponentType<any> | undefined;
71
+
72
+ /**
73
+ * Check if a component is registered.
74
+ *
75
+ * @param name - The name of the component
76
+ * @returns True if the component is registered
77
+ */
78
+ has(name: string): boolean;
79
+
80
+ /**
81
+ * Get all registered component names.
82
+ *
83
+ * @returns Array of component names
84
+ */
85
+ getNames(): string[];
29
86
  }
30
87
 
31
88
  /**
32
- * Tool call status types.
89
+ * The minimal required properties for the component.
33
90
  */
34
- export type ToolCallStatus =
35
- | 'pending'
36
- | 'awaiting_approval'
37
- | 'approved'
38
- | 'rejected'
39
- | 'completed'
40
- | 'error';
91
+ export interface IComponentProps {
92
+ /**
93
+ * The translation bundle.
94
+ */
95
+ trans: TranslationBundle;
96
+ }
97
+
98
+ /**
99
+ * A file diff target.
100
+ */
101
+ export interface IInlineDiffFileTarget {
102
+ /**
103
+ * Discriminator for a regular file diff target.
104
+ */
105
+ kind: 'file';
106
+ /**
107
+ * Path of the file being diffed.
108
+ */
109
+ path: string;
110
+ }
111
+
112
+ /**
113
+ * A notebook cell diff target.
114
+ */
115
+ export interface IInlineDiffNotebookCellTarget {
116
+ /**
117
+ * Discriminator for a notebook cell source diff target.
118
+ */
119
+ kind: 'cell';
120
+ /**
121
+ * Path of the notebook containing the cell.
122
+ */
123
+ notebookPath: string;
124
+ /**
125
+ * Stable cell identifier, when available from the producer.
126
+ */
127
+ cellId?: string;
128
+ /**
129
+ * Zero-based notebook cell index used for the default display label.
130
+ */
131
+ cellIndex?: number;
132
+ }
133
+
134
+ /**
135
+ * A supported inline diff target.
136
+ */
137
+ export type IInlineDiffTarget =
138
+ | IInlineDiffFileTarget
139
+ | IInlineDiffNotebookCellTarget;
140
+
141
+ /**
142
+ * A single inline diff entry.
143
+ */
144
+ export interface IInlineDiff {
145
+ /**
146
+ * Structured target metadata.
147
+ */
148
+ target: IInlineDiffTarget;
149
+ /**
150
+ * Optional explicit label for the diff header.
151
+ */
152
+ label?: string;
153
+ /**
154
+ * Updated text content for the diff target.
155
+ */
156
+ newText: string;
157
+ /**
158
+ * Previous text content for the diff target.
159
+ */
160
+ oldText?: string;
161
+ }
162
+
163
+ /**
164
+ * Metadata for rendering inline diffs.
165
+ */
166
+ export interface IInlineDiffMetadata {
167
+ /**
168
+ * List of inline diff entries to render.
169
+ */
170
+ diffs: IInlineDiff[];
171
+ }
172
+
173
+ /**
174
+ * A single queued message entry.
175
+ */
176
+ export interface IQueuedMessage {
177
+ id: string;
178
+ body: string;
179
+ }
41
180
 
42
181
  /**
43
- * Options for building tool call HTML.
182
+ * Metadata for the message queue component.
44
183
  */
45
- export interface IToolCallMetadata {
46
- toolName: string;
47
- input: string;
48
- status: ToolCallStatus;
49
- summary?: string;
50
- output?: string;
184
+ export interface IMessageQueueMetadata {
185
+ messages: IQueuedMessage[];
51
186
  targetId?: string;
52
- approvalId?: string;
53
187
  }
package/style/base.css CHANGED
@@ -82,22 +82,38 @@
82
82
  }
83
83
 
84
84
  .jp-ai-tool-status-pending {
85
- background: rgb(var(--jp-warn-color1-rgb) / 15%);
85
+ background: color-mix(
86
+ in srgb,
87
+ var(--jp-warn-color1, #f57c00) 15%,
88
+ transparent
89
+ );
86
90
  color: var(--jp-warn-color1);
87
91
  }
88
92
 
89
93
  .jp-ai-tool-status-completed {
90
- background: rgb(var(--jp-success-color1-rgb) / 15%);
94
+ background: color-mix(
95
+ in srgb,
96
+ var(--jp-success-color1, #388e3c) 15%,
97
+ transparent
98
+ );
91
99
  color: var(--jp-success-color1);
92
100
  }
93
101
 
94
102
  .jp-ai-tool-status-error {
95
- background: rgb(var(--jp-error-color1-rgb) / 15%);
103
+ background: color-mix(
104
+ in srgb,
105
+ var(--jp-error-color1, #d32f2f) 15%,
106
+ transparent
107
+ );
96
108
  color: var(--jp-error-color1);
97
109
  }
98
110
 
99
111
  .jp-ai-tool-status-approval {
100
- background: rgb(var(--jp-warn-color1-rgb) / 15%);
112
+ background: color-mix(
113
+ in srgb,
114
+ var(--jp-warn-color1, #f57c00) 15%,
115
+ transparent
116
+ );
101
117
  color: var(--jp-warn-color1);
102
118
  }
103
119
 
@@ -205,3 +221,163 @@
205
221
  cursor: not-allowed;
206
222
  opacity: 0.5;
207
223
  }
224
+
225
+ /* Inline Diff */
226
+ .jp-ai-inline-diff-container {
227
+ display: flex;
228
+ flex-direction: column;
229
+ gap: 8px;
230
+ margin: 8px 0;
231
+ }
232
+
233
+ .jp-ai-inline-diff-block {
234
+ overflow: hidden;
235
+ border: 1px solid var(--jp-border-color1);
236
+ border-radius: 6px;
237
+ background: var(--jp-layout-color0);
238
+ }
239
+
240
+ .jp-ai-inline-diff-header {
241
+ width: 100%;
242
+ padding: 6px 10px;
243
+ border: none;
244
+ background: var(--jp-layout-color1);
245
+ color: var(--jp-ui-font-color1);
246
+ font-family: var(--jp-code-font-family);
247
+ font-size: var(--jp-ui-font-size0);
248
+ text-align: left;
249
+ }
250
+
251
+ .jp-ai-inline-diff-content {
252
+ font-family: var(--jp-code-font-family);
253
+ font-size: var(--jp-code-font-size);
254
+ line-height: var(--jp-code-line-height);
255
+ }
256
+
257
+ .jp-ai-inline-diff-line {
258
+ display: grid;
259
+ grid-template-columns: auto minmax(0, 1fr);
260
+ column-gap: 8px;
261
+ align-items: start;
262
+ padding: 0 10px;
263
+ min-height: calc(var(--jp-code-line-height) * 1em);
264
+ }
265
+
266
+ .jp-ai-inline-diff-line-prefix {
267
+ width: 1ch;
268
+ color: var(--jp-ui-font-color3);
269
+ user-select: none;
270
+ text-align: center;
271
+ }
272
+
273
+ .jp-ai-inline-diff-line-text {
274
+ min-width: 0;
275
+ white-space: pre-wrap;
276
+ word-break: break-word;
277
+ }
278
+
279
+ .jp-ai-inline-diff-line-text:empty::before {
280
+ content: '·';
281
+ opacity: 0.35;
282
+ }
283
+
284
+ .jp-ai-inline-diff-line.jp-mod-added {
285
+ background: color-mix(
286
+ in srgb,
287
+ var(--jp-success-color1, #388e3c) 15%,
288
+ transparent
289
+ );
290
+ }
291
+
292
+ .jp-ai-inline-diff-line.jp-mod-removed {
293
+ background: color-mix(
294
+ in srgb,
295
+ var(--jp-error-color1, #d32f2f) 15%,
296
+ transparent
297
+ );
298
+ }
299
+
300
+ .jp-ai-inline-diff-line.jp-mod-context {
301
+ color: var(--jp-ui-font-color2);
302
+ }
303
+
304
+ .jp-ai-inline-diff-empty {
305
+ padding: 6px 10px;
306
+ color: var(--jp-ui-font-color2);
307
+ font-style: italic;
308
+ }
309
+
310
+ .jp-ai-inline-diff-toggle {
311
+ padding: 4px 10px 8px;
312
+ border: none;
313
+ background: none;
314
+ color: var(--jp-ui-font-color2);
315
+ font-family: var(--jp-ui-font-family);
316
+ font-size: var(--jp-ui-font-size0);
317
+ font-style: italic;
318
+ cursor: pointer;
319
+ text-align: left;
320
+ }
321
+
322
+ .jp-ai-inline-diff-toggle:hover {
323
+ color: var(--jp-ui-font-color1);
324
+ text-decoration: underline;
325
+ }
326
+
327
+ /* Message Queue Styling */
328
+ .jp-chat-message-queue {
329
+ display: flex;
330
+ flex-direction: column;
331
+ align-items: flex-end;
332
+ gap: 8px;
333
+ pointer-events: none;
334
+ width: 100%;
335
+ }
336
+
337
+ .jp-chat-message-queue-bubble {
338
+ position: relative;
339
+ display: inline-flex;
340
+ align-items: center;
341
+ gap: 6px;
342
+ background-color: var(--jp-layout-color2);
343
+ border: 1px solid var(--jp-border-color1);
344
+ border-radius: 16px;
345
+ padding: 4px 28px 4px 12px;
346
+ pointer-events: auto;
347
+ }
348
+
349
+ .jp-chat-message-queue-text {
350
+ font-size: var(--jp-ui-font-size0);
351
+ overflow: hidden;
352
+ text-overflow: ellipsis;
353
+ white-space: nowrap;
354
+ }
355
+
356
+ .jp-chat-message-queue-remove {
357
+ position: absolute;
358
+ right: 6px;
359
+ top: 50%;
360
+ transform: translateY(-50%);
361
+ display: inline-flex;
362
+ align-items: center;
363
+ justify-content: center;
364
+ width: 16px;
365
+ height: 16px;
366
+ padding: 0;
367
+ border: none;
368
+ border-radius: 50%;
369
+ background: transparent;
370
+ color: var(--jp-ui-font-color2);
371
+ font-size: 10px;
372
+ cursor: pointer;
373
+ opacity: 0;
374
+ }
375
+
376
+ .jp-chat-message-queue-remove:hover {
377
+ background: var(--jp-layout-color3);
378
+ color: var(--jp-ui-font-color1);
379
+ }
380
+
381
+ .jp-chat-message-queue-bubble:hover .jp-chat-message-queue-remove {
382
+ opacity: 1;
383
+ }