@jupyterlite/ai 0.9.1 → 0.10.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 (66) hide show
  1. package/README.md +5 -214
  2. package/lib/agent.d.ts +58 -66
  3. package/lib/agent.js +274 -300
  4. package/lib/approval-buttons.d.ts +19 -82
  5. package/lib/approval-buttons.js +36 -289
  6. package/lib/chat-model-registry.d.ts +6 -0
  7. package/lib/chat-model-registry.js +4 -1
  8. package/lib/chat-model.d.ts +19 -54
  9. package/lib/chat-model.js +243 -303
  10. package/lib/components/clear-button.d.ts +6 -1
  11. package/lib/components/clear-button.js +8 -3
  12. package/lib/components/completion-status.d.ts +5 -0
  13. package/lib/components/completion-status.js +5 -4
  14. package/lib/components/model-select.d.ts +6 -1
  15. package/lib/components/model-select.js +9 -8
  16. package/lib/components/stop-button.d.ts +6 -1
  17. package/lib/components/stop-button.js +8 -3
  18. package/lib/components/token-usage-display.d.ts +5 -0
  19. package/lib/components/token-usage-display.js +2 -2
  20. package/lib/components/tool-select.d.ts +6 -1
  21. package/lib/components/tool-select.js +6 -5
  22. package/lib/index.js +58 -38
  23. package/lib/models/settings-model.d.ts +1 -1
  24. package/lib/providers/built-in-providers.js +38 -19
  25. package/lib/providers/models.d.ts +3 -3
  26. package/lib/providers/provider-registry.d.ts +3 -4
  27. package/lib/providers/provider-registry.js +1 -4
  28. package/lib/tokens.d.ts +5 -6
  29. package/lib/tools/commands.d.ts +2 -1
  30. package/lib/tools/commands.js +37 -46
  31. package/lib/tools/file.js +49 -73
  32. package/lib/tools/notebook.js +370 -445
  33. package/lib/widgets/ai-settings.d.ts +6 -0
  34. package/lib/widgets/ai-settings.js +72 -71
  35. package/lib/widgets/main-area-chat.d.ts +2 -0
  36. package/lib/widgets/main-area-chat.js +5 -2
  37. package/lib/widgets/provider-config-dialog.d.ts +2 -0
  38. package/lib/widgets/provider-config-dialog.js +34 -34
  39. package/package.json +12 -12
  40. package/src/agent.ts +342 -361
  41. package/src/approval-buttons.ts +43 -389
  42. package/src/chat-model-registry.ts +9 -1
  43. package/src/chat-model.ts +355 -370
  44. package/src/completion/completion-provider.ts +2 -3
  45. package/src/components/clear-button.tsx +16 -3
  46. package/src/components/completion-status.tsx +18 -4
  47. package/src/components/model-select.tsx +21 -8
  48. package/src/components/stop-button.tsx +16 -3
  49. package/src/components/token-usage-display.tsx +14 -2
  50. package/src/components/tool-select.tsx +23 -5
  51. package/src/index.ts +75 -36
  52. package/src/models/settings-model.ts +1 -1
  53. package/src/providers/built-in-providers.ts +38 -19
  54. package/src/providers/models.ts +3 -3
  55. package/src/providers/provider-registry.ts +4 -8
  56. package/src/tokens.ts +5 -6
  57. package/src/tools/commands.ts +39 -50
  58. package/src/tools/file.ts +49 -75
  59. package/src/tools/notebook.ts +451 -510
  60. package/src/widgets/ai-settings.tsx +153 -84
  61. package/src/widgets/main-area-chat.ts +8 -2
  62. package/src/widgets/provider-config-dialog.tsx +54 -41
  63. package/style/base.css +13 -73
  64. package/lib/mcp/browser.d.ts +0 -68
  65. package/lib/mcp/browser.js +0 -138
  66. package/src/mcp/browser.ts +0 -220
@@ -1,5 +1,6 @@
1
1
  import { IThemeManager } from '@jupyterlab/apputils';
2
2
  import { ReactWidget } from '@jupyterlab/ui-components';
3
+ import type { TranslationBundle } from '@jupyterlab/translation';
3
4
  import { ISecretsManager } from 'jupyter-secrets-manager';
4
5
  import React from 'react';
5
6
  import { AgentManagerFactory } from '../agent';
@@ -24,6 +25,7 @@ export declare class AISettingsWidget extends ReactWidget {
24
25
  private _themeManager?;
25
26
  private _providerRegistry;
26
27
  private _secretsManager?;
28
+ private _trans;
27
29
  }
28
30
  /**
29
31
  * Namespace for AISettingsWidget types and interfaces
@@ -45,5 +47,9 @@ export declare namespace AISettingsWidget {
45
47
  * The token used to request the secrets manager.
46
48
  */
47
49
  token: symbol;
50
+ /**
51
+ * The application language translation bundle.
52
+ */
53
+ trans: TranslationBundle;
48
54
  }
49
55
  }
@@ -46,9 +46,10 @@ export class AISettingsWidget extends ReactWidget {
46
46
  this._themeManager = options.themeManager;
47
47
  this._providerRegistry = options.providerRegistry;
48
48
  this._secretsManager = options.secretsManager;
49
+ this._trans = options.trans;
49
50
  this.id = 'jupyterlite-ai-settings';
50
- this.title.label = 'AI Settings';
51
- this.title.caption = 'Configure AI providers and behavior';
51
+ this.title.label = this._trans.__('AI Settings');
52
+ this.title.caption = this._trans.__('Configure AI providers and behavior');
52
53
  this.title.closable = true;
53
54
  }
54
55
  /**
@@ -56,22 +57,23 @@ export class AISettingsWidget extends ReactWidget {
56
57
  * @returns A React element containing the AI settings interface
57
58
  */
58
59
  render() {
59
- return (React.createElement(AISettingsComponent, { model: this._settingsModel, agentManagerFactory: this._agentManagerFactory, themeManager: this._themeManager, providerRegistry: this._providerRegistry, secretsManager: this._secretsManager }));
60
+ return (React.createElement(AISettingsComponent, { model: this._settingsModel, agentManagerFactory: this._agentManagerFactory, themeManager: this._themeManager, providerRegistry: this._providerRegistry, secretsManager: this._secretsManager, trans: this._trans }));
60
61
  }
61
62
  _settingsModel;
62
63
  _agentManagerFactory;
63
64
  _themeManager;
64
65
  _providerRegistry;
65
66
  _secretsManager;
67
+ _trans;
66
68
  }
67
69
  /**
68
70
  * The main AI settings component that provides configuration UI
69
71
  * @param props - Component props containing models and theme manager
70
72
  * @returns A React component for AI settings configuration
71
73
  */
72
- const AISettingsComponent = ({ model, agentManagerFactory, themeManager, providerRegistry, secretsManager }) => {
74
+ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, providerRegistry, secretsManager, trans }) => {
73
75
  if (!model) {
74
- return React.createElement("div", null, "Settings model not available");
76
+ return React.createElement("div", null, trans.__('Settings model not available'));
75
77
  }
76
78
  const [config, setConfig] = useState(model.config || {});
77
79
  const [theme, setTheme] = useState(() => createJupyterLabTheme(themeManager));
@@ -358,28 +360,28 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
358
360
  } },
359
361
  React.createElement(Box, { sx: { mb: 2, display: 'flex', alignItems: 'center', gap: 2 } },
360
362
  React.createElement(Settings, { color: "primary", sx: { fontSize: 24 } }),
361
- React.createElement(Typography, { variant: "h5", component: "h1", sx: { fontWeight: 600 } }, "AI Settings")),
363
+ React.createElement(Typography, { variant: "h5", component: "h1", sx: { fontWeight: 600 } }, trans.__('AI Settings'))),
362
364
  React.createElement(Box, { sx: { borderBottom: 1, borderColor: 'divider', mb: 2 } },
363
365
  React.createElement(Tabs, { value: activeTab, onChange: (_, newValue) => setActiveTab(newValue) },
364
- React.createElement(Tab, { label: "Providers" }),
365
- React.createElement(Tab, { label: "Behavior" }),
366
- React.createElement(Tab, { label: "MCP Servers" }))),
366
+ React.createElement(Tab, { label: trans.__('Providers') }),
367
+ React.createElement(Tab, { label: trans.__('Behavior') }),
368
+ React.createElement(Tab, { label: trans.__('MCP Servers') }))),
367
369
  activeTab === 0 && (React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 } },
368
370
  config.providers.length > 0 && (React.createElement(Card, { elevation: 2 },
369
371
  React.createElement(CardContent, null,
370
- React.createElement(Typography, { variant: "h6", component: "h2", gutterBottom: true }, "Default Providers"),
372
+ React.createElement(Typography, { variant: "h6", component: "h2", gutterBottom: true }, trans.__('Default Providers')),
371
373
  React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 } },
372
374
  React.createElement(FormControl, { fullWidth: true },
373
- React.createElement(InputLabel, null, "Chat Provider"),
374
- React.createElement(Select, { value: config.defaultProvider, label: "Chat Provider", onChange: e => model.setActiveProvider(e.target.value) }, config.providers.map(provider => (React.createElement(MenuItem, { key: provider.id, value: provider.id }, provider.name))))),
375
+ React.createElement(InputLabel, null, trans.__('Chat Provider')),
376
+ React.createElement(Select, { value: config.defaultProvider, label: trans.__('Chat Provider'), onChange: e => model.setActiveProvider(e.target.value) }, config.providers.map(provider => (React.createElement(MenuItem, { key: provider.id, value: provider.id }, provider.name))))),
375
377
  React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: config.useSameProviderForChatAndCompleter, onChange: e => handleConfigUpdate({
376
378
  useSameProviderForChatAndCompleter: e.target.checked
377
- }), color: "primary" }), label: "Use same provider for chat and completions" }),
379
+ }), color: "primary" }), label: trans.__('Use same provider for chat and completions') }),
378
380
  !config.useSameProviderForChatAndCompleter && (React.createElement(FormControl, { fullWidth: true },
379
- React.createElement(InputLabel, null, "Completion Provider"),
380
- React.createElement(Select, { value: config.activeCompleterProvider || '', label: "Completion Provider", className: "jp-ai-completion-provider-select", onChange: e => model.setActiveCompleterProvider(e.target.value || undefined) },
381
+ React.createElement(InputLabel, null, trans.__('Completion Provider')),
382
+ React.createElement(Select, { value: config.activeCompleterProvider || '', label: trans.__('Completion Provider'), className: "jp-ai-completion-provider-select", onChange: e => model.setActiveCompleterProvider(e.target.value || undefined) },
381
383
  React.createElement(MenuItem, { value: "" },
382
- React.createElement("em", null, "No completion")),
384
+ React.createElement("em", null, trans.__('No completion'))),
383
385
  config.providers.map(provider => (React.createElement(MenuItem, { key: provider.id, value: provider.id }, provider.name)))))))))),
384
386
  React.createElement(Card, { elevation: 2 },
385
387
  React.createElement(CardContent, null,
@@ -390,9 +392,9 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
390
392
  mb: 2
391
393
  } },
392
394
  React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 } },
393
- React.createElement(Typography, { variant: "h6", component: "h2" }, "Configured Providers")),
394
- React.createElement(Button, { variant: "contained", startIcon: React.createElement(Add, null), onClick: openAddDialog, size: "small" }, "Add Provider")),
395
- config.providers.length === 0 ? (React.createElement(Alert, { severity: "info" }, "No providers configured yet. Click \"Add Provider\" to get started.")) : (React.createElement(List, null, config.providers.map(provider => {
395
+ React.createElement(Typography, { variant: "h6", component: "h2" }, trans.__('Configured Providers'))),
396
+ React.createElement(Button, { variant: "contained", startIcon: React.createElement(Add, null), onClick: openAddDialog, size: "small" }, trans.__('Add Provider'))),
397
+ config.providers.length === 0 ? (React.createElement(Alert, { severity: "info" }, trans.__('No providers configured yet. Click "Add Provider" to get started.'))) : (React.createElement(List, null, config.providers.map(provider => {
396
398
  const isActive = config.defaultProvider === provider.id;
397
399
  const isActiveCompleter = config.useSameProviderForChatAndCompleter
398
400
  ? isActive
@@ -418,8 +420,8 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
418
420
  mb: 0.5
419
421
  } },
420
422
  React.createElement(Typography, { variant: "subtitle1", fontWeight: "medium" }, provider.name),
421
- isActive && (React.createElement(Chip, { label: "Chat", size: "small", color: "primary", icon: React.createElement(CheckCircle, null) })),
422
- isActiveCompleter && (React.createElement(Chip, { label: "Completion", size: "small", color: "secondary", icon: React.createElement(CheckCircle, null) }))),
423
+ isActive && (React.createElement(Chip, { label: trans.__('Chat'), size: "small", color: "primary", icon: React.createElement(CheckCircle, null) })),
424
+ isActiveCompleter && (React.createElement(Chip, { label: trans.__('Completion'), size: "small", color: "secondary", icon: React.createElement(CheckCircle, null) }))),
423
425
  React.createElement(Typography, { variant: "body2", color: "text.secondary", gutterBottom: true },
424
426
  provider.provider,
425
427
  " \u2022 ",
@@ -428,67 +430,67 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
428
430
  ` • ${provider.description}`),
429
431
  params &&
430
432
  (params.temperature !== undefined ||
431
- params.maxTokens !== undefined ||
433
+ params.maxOutputTokens !== undefined ||
432
434
  params.maxTurns !== undefined) && (React.createElement(Box, { sx: {
433
435
  display: 'flex',
434
436
  flexWrap: 'wrap',
435
437
  gap: 1,
436
438
  mt: 1
437
439
  } },
438
- params.temperature !== undefined && (React.createElement(Chip, { label: `Temp: ${params.temperature}`, size: "small", variant: "outlined" })),
439
- params.maxTokens !== undefined && (React.createElement(Chip, { label: `Tokens: ${params.maxTokens}`, size: "small", variant: "outlined" })),
440
- params.maxTurns !== undefined && (React.createElement(Chip, { label: `Turns: ${params.maxTurns}`, size: "small", variant: "outlined" }))))),
440
+ params.temperature !== undefined && (React.createElement(Chip, { label: trans.__('Temp: %1', params.temperature), size: "small", variant: "outlined" })),
441
+ params.maxOutputTokens !== undefined && (React.createElement(Chip, { label: trans.__('Tokens: %1', params.maxOutputTokens), size: "small", variant: "outlined" })),
442
+ params.maxTurns !== undefined && (React.createElement(Chip, { label: trans.__('Turns: %1', params.maxTurns), size: "small", variant: "outlined" }))))),
441
443
  React.createElement(IconButton, { onClick: e => handleMenuClick(e, provider.id), size: "small" },
442
444
  React.createElement(MoreVert, null)))));
443
445
  }))))),
444
446
  secretsManager !== undefined && (React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: config.useSecretsManager, onChange: e => handleConfigUpdate({
445
447
  useSecretsManager: e.target.checked
446
448
  }), color: "primary", sx: { alignSelf: 'flex-start' } }), label: React.createElement("div", null,
447
- React.createElement("span", null, "Use the secrets manager to manage API keys"),
448
- !config.useSecretsManager && (React.createElement(Alert, { severity: "warning", icon: React.createElement(Error, null), sx: { mb: 2 } }, "The secrets are stored in plain text in settings"))) })))),
449
+ React.createElement("span", null, trans.__('Use the secrets manager to manage API keys')),
450
+ !config.useSecretsManager && (React.createElement(Alert, { severity: "warning", icon: React.createElement(Error, null), sx: { mb: 2 } }, trans.__('The secrets are stored in plain text in settings')))) })))),
449
451
  activeTab === 1 && (React.createElement(Card, { elevation: 2 },
450
452
  React.createElement(CardContent, null,
451
- React.createElement(Typography, { variant: "h6", component: "h2", gutterBottom: true }, "Behavior Settings"),
453
+ React.createElement(Typography, { variant: "h6", component: "h2", gutterBottom: true }, trans.__('Behavior Settings')),
452
454
  React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 } },
453
455
  React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: config.toolsEnabled, onChange: e => handleConfigUpdate({
454
456
  toolsEnabled: e.target.checked
455
457
  }), color: "primary" }), label: React.createElement(Box, null,
456
- React.createElement(Typography, { variant: "body1" }, "Enable Tools"),
457
- React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Allow the AI to use tools like notebook operations, code execution, and file management")) }),
458
+ React.createElement(Typography, { variant: "body1" }, trans.__('Enable Tools')),
459
+ React.createElement(Typography, { variant: "caption", color: "text.secondary" }, trans.__('Allow the AI to use tools like notebook operations, code execution, and file management'))) }),
458
460
  React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: config.sendWithShiftEnter, onChange: e => handleConfigUpdate({
459
461
  sendWithShiftEnter: e.target.checked
460
462
  }), color: "primary" }), label: React.createElement(Box, null,
461
- React.createElement(Typography, { variant: "body1" }, "Send with Shift+Enter"),
462
- React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Use Shift+Enter to send messages (Enter creates new line)")) }),
463
+ React.createElement(Typography, { variant: "body1" }, trans.__('Send with Shift+Enter')),
464
+ React.createElement(Typography, { variant: "caption", color: "text.secondary" }, trans.__('Use Shift+Enter to send messages (Enter creates new line)'))) }),
463
465
  React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: config.showTokenUsage, onChange: e => handleConfigUpdate({
464
466
  showTokenUsage: e.target.checked
465
467
  }), color: "primary" }), label: React.createElement(Box, null,
466
- React.createElement(Typography, { variant: "body1" }, "Show Token Usage"),
467
- React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Display token usage information in the chat toolbar")) }),
468
+ React.createElement(Typography, { variant: "body1" }, trans.__('Show Token Usage')),
469
+ React.createElement(Typography, { variant: "caption", color: "text.secondary" }, trans.__('Display token usage information in the chat toolbar'))) }),
468
470
  React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: config.showCellDiff, onChange: e => handleConfigUpdate({
469
471
  showCellDiff: e.target.checked
470
472
  }), color: "primary" }), label: React.createElement(Box, null,
471
- React.createElement(Typography, { variant: "body1" }, "Show Cell Diff"),
472
- React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Show diff view when AI modifies cell content")) }),
473
+ React.createElement(Typography, { variant: "body1" }, trans.__('Show Cell Diff')),
474
+ React.createElement(Typography, { variant: "caption", color: "text.secondary" }, trans.__('Show diff view when AI modifies cell content'))) }),
473
475
  config.showCellDiff && (React.createElement(FormControl, { sx: { ml: 4 } },
474
- React.createElement(InputLabel, null, "Diff Display Mode"),
475
- React.createElement(Select, { value: config.diffDisplayMode, label: "Diff Display Mode", onChange: e => handleConfigUpdate({
476
+ React.createElement(InputLabel, null, trans.__('Diff Display Mode')),
477
+ React.createElement(Select, { value: config.diffDisplayMode, label: trans.__('Diff Display Mode'), onChange: e => handleConfigUpdate({
476
478
  diffDisplayMode: e.target.value
477
479
  }) },
478
- React.createElement(MenuItem, { value: "split" }, "Split View"),
479
- React.createElement(MenuItem, { value: "unified" }, "Unified View")))),
480
+ React.createElement(MenuItem, { value: "split" }, trans.__('Split View')),
481
+ React.createElement(MenuItem, { value: "unified" }, trans.__('Unified View'))))),
480
482
  React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: config.showFileDiff, onChange: e => handleConfigUpdate({
481
483
  showFileDiff: e.target.checked
482
484
  }), color: "primary" }), label: React.createElement(Box, null,
483
- React.createElement(Typography, { variant: "body1" }, "Show File Diff"),
484
- React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Show diff view when AI modifies file content")) }),
485
+ React.createElement(Typography, { variant: "body1" }, trans.__('Show File Diff')),
486
+ React.createElement(Typography, { variant: "caption", color: "text.secondary" }, trans.__('Show diff view when AI modifies file content'))) }),
485
487
  React.createElement(Divider, { sx: { my: 1 } }),
486
- React.createElement(TextField, { fullWidth: true, multiline: true, rows: 3, label: "System Prompt", value: systemPromptValue, onChange: e => handleSystemPromptChange(e.target.value), placeholder: "Define the AI's behavior and personality...", helperText: "Instructions that define how the AI should behave and respond" }),
487
- React.createElement(TextField, { fullWidth: true, multiline: true, rows: 3, label: "Completion System Prompt", value: completionPromptValue, onChange: e => handleCompletionPromptChange(e.target.value), placeholder: "Define how the AI should generate code completions...", helperText: "Instructions that define how the AI should generate code completions" }),
488
+ React.createElement(TextField, { fullWidth: true, multiline: true, rows: 3, label: trans.__('System Prompt'), value: systemPromptValue, onChange: e => handleSystemPromptChange(e.target.value), placeholder: trans.__("Define the AI's behavior and personality..."), helperText: trans.__('Instructions that define how the AI should behave and respond') }),
489
+ React.createElement(TextField, { fullWidth: true, multiline: true, rows: 3, label: trans.__('Completion System Prompt'), value: completionPromptValue, onChange: e => handleCompletionPromptChange(e.target.value), placeholder: trans.__('Define how the AI should generate code completions...'), helperText: trans.__('Instructions that define how the AI should generate code completions') }),
488
490
  React.createElement(Divider, { sx: { my: 2 } }),
489
491
  React.createElement(Box, null,
490
- React.createElement(Typography, { variant: "body1", gutterBottom: true }, "Commands Requiring Approval"),
491
- React.createElement(Typography, { variant: "caption", color: "text.secondary", gutterBottom: true, sx: { display: 'block' } }, "Commands that require user approval before AI can execute them"),
492
+ React.createElement(Typography, { variant: "body1", gutterBottom: true }, trans.__('Commands Requiring Approval')),
493
+ React.createElement(Typography, { variant: "caption", color: "text.secondary", gutterBottom: true, sx: { display: 'block' } }, trans.__('Commands that require user approval before AI can execute them')),
492
494
  React.createElement(List, { sx: { mb: 2, maxHeight: 200, overflow: 'auto' } }, config.commandsRequiringApproval.map((command, index) => (React.createElement(ListItem, { key: index, divider: true },
493
495
  React.createElement(ListItemText, { primary: command }),
494
496
  React.createElement(ListItemSecondaryAction, null,
@@ -502,7 +504,7 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
502
504
  });
503
505
  }, size: "small" },
504
506
  React.createElement(Delete, null))))))),
505
- React.createElement(TextField, { fullWidth: true, label: "Add New Command", placeholder: "e.g., notebook:run-cell", onKeyDown: e => {
507
+ React.createElement(TextField, { fullWidth: true, label: trans.__('Add New Command'), placeholder: trans.__('e.g., notebook:run-cell'), onKeyDown: e => {
506
508
  if (e.key === 'Enter') {
507
509
  const value = e.target.value.trim();
508
510
  if (value &&
@@ -517,7 +519,7 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
517
519
  e.target.value = '';
518
520
  }
519
521
  }
520
- }, helperText: "Press Enter to add a command. Common commands: notebook:run-cell, console:execute, fileeditor:run-code" })))))),
522
+ }, helperText: trans.__('Press Enter to add a command. Common commands: notebook:run-cell, console:execute, fileeditor:run-code') })))))),
521
523
  activeTab === 2 && (React.createElement(Card, { elevation: 2 },
522
524
  React.createElement(CardContent, null,
523
525
  React.createElement(Box, { sx: {
@@ -528,10 +530,10 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
528
530
  } },
529
531
  React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 } },
530
532
  React.createElement(Cable, { color: "primary" }),
531
- React.createElement(Typography, { variant: "h6", component: "h2" }, "Remote MCP Servers")),
532
- React.createElement(Button, { variant: "contained", startIcon: React.createElement(Add, null), onClick: openAddMCPDialog, size: "small" }, "Add Server")),
533
- React.createElement(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 } }, "Configure remote Model Context Protocol (MCP) servers to extend the AI's capabilities with external tools and data sources."),
534
- config.mcpServers.length === 0 ? (React.createElement(Alert, { severity: "info" }, "No MCP servers configured yet. Click \"Add Server\" to connect to remote MCP services.")) : (React.createElement(List, null, config.mcpServers.map(server => (React.createElement(ListItem, { key: server.id, divider: true },
533
+ React.createElement(Typography, { variant: "h6", component: "h2" }, trans.__('Remote MCP Servers'))),
534
+ React.createElement(Button, { variant: "contained", startIcon: React.createElement(Add, null), onClick: openAddMCPDialog, size: "small" }, trans.__('Add Server'))),
535
+ React.createElement(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 } }, trans.__("Configure remote Model Context Protocol (MCP) servers to extend the AI's capabilities with external tools and data sources.")),
536
+ config.mcpServers.length === 0 ? (React.createElement(Alert, { severity: "info" }, trans.__('No MCP servers configured yet. Click "Add Server" to connect to remote MCP services.'))) : (React.createElement(List, null, config.mcpServers.map(server => (React.createElement(ListItem, { key: server.id, divider: true },
535
537
  React.createElement(ListItemText, { primary: React.createElement(Box, { sx: {
536
538
  display: 'flex',
537
539
  alignItems: 'center',
@@ -546,16 +548,13 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
546
548
  enabled: e.target.checked
547
549
  }), size: "small", color: "primary" })), secondary: React.createElement(Box, null,
548
550
  React.createElement(Typography, { variant: "body2", color: "text.secondary" }, server.url),
549
- server.enabled && agentManagerFactory && (React.createElement(Typography, { variant: "caption", color: "text.secondary" },
550
- "Status:",
551
- ' ',
552
- agentManagerFactory.isMCPServerConnected(server.name)
553
- ? 'Connected'
554
- : 'Connection failed'))) }),
551
+ server.enabled && agentManagerFactory && (React.createElement(Typography, { variant: "caption", color: "text.secondary" }, trans.__('Status: %1', agentManagerFactory.isMCPServerConnected(server.name)
552
+ ? trans.__('Connected')
553
+ : trans.__('Connection failed'))))) }),
555
554
  React.createElement(ListItemSecondaryAction, null,
556
555
  React.createElement(IconButton, { onClick: e => handleMCPMenuClick(e, server.id), size: "small" },
557
556
  React.createElement(MoreVert, null))))))))))),
558
- React.createElement(ProviderConfigDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSave: editingProvider ? handleEditProvider : handleAddProvider, initialConfig: editingProvider, mode: editingProvider ? 'edit' : 'add', providerRegistry: providerRegistry, handleSecretField: handleSecretField }),
557
+ React.createElement(ProviderConfigDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSave: editingProvider ? handleEditProvider : handleAddProvider, initialConfig: editingProvider, mode: editingProvider ? 'edit' : 'add', providerRegistry: providerRegistry, handleSecretField: handleSecretField, trans: trans }),
559
558
  React.createElement(Menu, { anchorEl: menuAnchor, open: Boolean(menuAnchor), onClose: handleMenuClose },
560
559
  React.createElement(MenuItem, { onClick: () => {
561
560
  const provider = config.providers.find(p => p.id === menuProviderId);
@@ -564,11 +563,11 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
564
563
  }
565
564
  } },
566
565
  React.createElement(Edit, { sx: { mr: 1 } }),
567
- "Edit"),
566
+ trans.__('Edit')),
568
567
  React.createElement(MenuItem, { onClick: () => handleDeleteProvider(menuProviderId), sx: { color: 'error.main' } },
569
568
  React.createElement(Delete, { sx: { mr: 1 } }),
570
- "Delete")),
571
- React.createElement(MCPServerDialog, { open: mcpDialogOpen, onClose: () => setMcpDialogOpen(false), onSave: editingMCPServer ? handleEditMCPServer : handleAddMCPServer, initialConfig: editingMCPServer, mode: editingMCPServer ? 'edit' : 'add' }),
569
+ trans.__('Delete'))),
570
+ React.createElement(MCPServerDialog, { open: mcpDialogOpen, onClose: () => setMcpDialogOpen(false), onSave: editingMCPServer ? handleEditMCPServer : handleAddMCPServer, initialConfig: editingMCPServer, mode: editingMCPServer ? 'edit' : 'add', trans: trans }),
572
571
  React.createElement(Menu, { anchorEl: mcpMenuAnchor, open: Boolean(mcpMenuAnchor), onClose: handleMCPMenuClose },
573
572
  React.createElement(MenuItem, { onClick: () => {
574
573
  const server = config.mcpServers.find(s => s.id === mcpMenuServerId);
@@ -577,17 +576,17 @@ const AISettingsComponent = ({ model, agentManagerFactory, themeManager, provide
577
576
  }
578
577
  } },
579
578
  React.createElement(Edit, { sx: { mr: 1 } }),
580
- "Edit"),
579
+ trans.__('Edit')),
581
580
  React.createElement(MenuItem, { onClick: () => handleDeleteMCPServer(mcpMenuServerId), sx: { color: 'error.main' } },
582
581
  React.createElement(Delete, { sx: { mr: 1 } }),
583
- "Delete")))));
582
+ trans.__('Delete'))))));
584
583
  };
585
584
  /**
586
585
  * Dialog component for adding/editing MCP server configurations
587
586
  * @param props - Component props for the MCP server dialog
588
587
  * @returns A React component for MCP server configuration
589
588
  */
590
- const MCPServerDialog = ({ open, onClose, onSave, initialConfig, mode }) => {
589
+ const MCPServerDialog = ({ open, onClose, onSave, initialConfig, mode, trans }) => {
591
590
  const [name, setName] = useState(initialConfig?.name || '');
592
591
  const [url, setUrl] = useState(initialConfig?.url || '');
593
592
  const [enabled, setEnabled] = useState(initialConfig?.enabled ?? true);
@@ -631,15 +630,17 @@ const MCPServerDialog = ({ open, onClose, onSave, initialConfig, mode }) => {
631
630
  };
632
631
  const canSave = name.trim() && url.trim() && _isValidUrl(url.trim());
633
632
  return (React.createElement(Dialog, { open: open, onClose: onClose, maxWidth: "sm", fullWidth: true },
634
- React.createElement(DialogTitle, null, mode === 'add' ? 'Add MCP Server' : 'Edit MCP Server'),
633
+ React.createElement(DialogTitle, null, mode === 'add'
634
+ ? trans.__('Add MCP Server')
635
+ : trans.__('Edit MCP Server')),
635
636
  React.createElement(DialogContent, null,
636
637
  React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2, pt: 1 } },
637
- React.createElement(TextField, { autoFocus: true, fullWidth: true, label: "Server Name", value: name, onChange: e => setName(e.target.value), placeholder: "My MCP Server", helperText: "A friendly name to identify this MCP server" }),
638
- React.createElement(TextField, { fullWidth: true, label: "Server URL", value: url, onChange: e => setUrl(e.target.value), placeholder: "https://example.com/mcp", helperText: "The HTTP/HTTPS URL of the MCP server", error: Boolean(url.trim() && !_isValidUrl(url.trim())) }),
639
- React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: enabled, onChange: e => setEnabled(e.target.checked), color: "primary" }), label: "Enable this server" }))),
638
+ React.createElement(TextField, { autoFocus: true, fullWidth: true, label: trans.__('Server Name'), value: name, onChange: e => setName(e.target.value), placeholder: trans.__('My MCP Server'), helperText: trans.__('A friendly name to identify this MCP server') }),
639
+ React.createElement(TextField, { fullWidth: true, label: trans.__('Server URL'), value: url, onChange: e => setUrl(e.target.value), placeholder: trans.__('https://example.com/mcp'), helperText: trans.__('The HTTP/HTTPS URL of the MCP server'), error: Boolean(url.trim() && !_isValidUrl(url.trim())) }),
640
+ React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: enabled, onChange: e => setEnabled(e.target.checked), color: "primary" }), label: trans.__('Enable this server') }))),
640
641
  React.createElement(DialogActions, null,
641
- React.createElement(Button, { onClick: onClose }, "Cancel"),
642
- React.createElement(Button, { onClick: handleSave, variant: "contained", disabled: !canSave }, mode === 'add' ? 'Add' : 'Save'))));
642
+ React.createElement(Button, { onClick: onClose }, trans.__('Cancel')),
643
+ React.createElement(Button, { onClick: handleSave, variant: "contained", disabled: !canSave }, mode === 'add' ? trans.__('Add') : trans.__('Save')))));
643
644
  };
644
645
  var Private;
645
646
  (function (Private) {
@@ -1,5 +1,6 @@
1
1
  import { ChatWidget } from '@jupyter/chat';
2
2
  import { MainAreaWidget } from '@jupyterlab/apputils';
3
+ import type { TranslationBundle } from '@jupyterlab/translation';
3
4
  import { CommandRegistry } from '@lumino/commands';
4
5
  import { AIChatModel } from '../chat-model';
5
6
  import { AISettingsModel } from '../models/settings-model';
@@ -7,6 +8,7 @@ export declare namespace MainAreaChat {
7
8
  interface IOptions extends MainAreaWidget.IOptions<ChatWidget> {
8
9
  commands: CommandRegistry;
9
10
  settingsModel: AISettingsModel;
11
+ trans: TranslationBundle;
10
12
  }
11
13
  }
12
14
  /**
@@ -10,6 +10,7 @@ export class MainAreaChat extends MainAreaWidget {
10
10
  constructor(options) {
11
11
  super(options);
12
12
  this.title.label = this.content.model.name;
13
+ const { trans } = options;
13
14
  // add the move to side button.
14
15
  this.toolbar.addItem('moveToSide', new CommandToolbarButton({
15
16
  commands: options.commands,
@@ -24,12 +25,14 @@ export class MainAreaChat extends MainAreaWidget {
24
25
  const tokenUsageWidget = new TokenUsageWidget({
25
26
  tokenUsageChanged: this.model.tokenUsageChanged,
26
27
  settingsModel: options.settingsModel,
27
- initialTokenUsage: this.model.agentManager.tokenUsage
28
+ initialTokenUsage: this.model.agentManager.tokenUsage,
29
+ translator: trans
28
30
  });
29
31
  this.toolbar.addItem('token-usage', tokenUsageWidget);
30
32
  // Add the approval button, tied to the chat widget.
31
33
  this._approvalButtons = new ApprovalButtons({
32
- chatPanel: this.content
34
+ chatPanel: this.content,
35
+ agentManager: this.model.agentManager
33
36
  });
34
37
  }
35
38
  dispose() {
@@ -1,3 +1,4 @@
1
+ import type { TranslationBundle } from '@jupyterlab/translation';
1
2
  import React from 'react';
2
3
  import { IProviderConfig } from '../models/settings-model';
3
4
  import type { IProviderRegistry } from '../tokens';
@@ -9,6 +10,7 @@ interface IProviderConfigDialogProps {
9
10
  mode: 'add' | 'edit';
10
11
  providerRegistry: IProviderRegistry;
11
12
  handleSecretField: (input: HTMLInputElement, provider: string, fieldName: string) => Promise<void>;
13
+ trans: TranslationBundle;
12
14
  }
13
15
  export declare const ProviderConfigDialog: React.FC<IProviderConfigDialogProps>;
14
16
  export {};
@@ -8,7 +8,7 @@ import React from 'react';
8
8
  */
9
9
  const DEFAULT_TEMPERATURE = 0.7;
10
10
  const DEFAULT_MAX_TURNS = 25;
11
- export const ProviderConfigDialog = ({ open, onClose, onSave, initialConfig, mode, providerRegistry, handleSecretField }) => {
11
+ export const ProviderConfigDialog = ({ open, onClose, onSave, initialConfig, mode, providerRegistry, handleSecretField, trans }) => {
12
12
  const apiKeyRef = React.useRef();
13
13
  const [name, setName] = React.useState(initialConfig?.name || '');
14
14
  const [provider, setProvider] = React.useState(initialConfig?.provider || 'anthropic');
@@ -88,40 +88,42 @@ export const ProviderConfigDialog = ({ open, onClose, onSave, initialConfig, mod
88
88
  model &&
89
89
  (selectedProvider?.apiKeyRequirement !== 'required' || apiKey);
90
90
  return (React.createElement(Dialog, { open: open, onClose: onClose, maxWidth: "md", fullWidth: true },
91
- React.createElement(DialogTitle, null, mode === 'add' ? 'Add New Provider' : 'Edit Provider'),
91
+ React.createElement(DialogTitle, null, mode === 'add'
92
+ ? trans.__('Add New Provider')
93
+ : trans.__('Edit Provider')),
92
94
  React.createElement(DialogContent, null,
93
95
  React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2, pt: 1 } },
94
- React.createElement(TextField, { fullWidth: true, label: "Provider Name", value: name, onChange: e => setName(e.target.value), placeholder: "e.g., My Anthropic Config, Work Provider", helperText: "A friendly name to identify this provider configuration", required: true }),
96
+ React.createElement(TextField, { fullWidth: true, label: trans.__('Provider Name'), value: name, onChange: e => setName(e.target.value), placeholder: trans.__('e.g., My Anthropic Config, Work Provider'), helperText: trans.__('A friendly name to identify this provider configuration'), required: true }),
95
97
  React.createElement(FormControl, { fullWidth: true, required: true },
96
- React.createElement(InputLabel, null, "Provider Type"),
97
- React.createElement(Select, { value: provider, label: "Provider Type", onChange: e => setProvider(e.target.value) }, providerOptions.map(option => (React.createElement(MenuItem, { key: option.value, value: option.value },
98
+ React.createElement(InputLabel, null, trans.__('Provider Type')),
99
+ React.createElement(Select, { value: provider, label: trans.__('Provider Type'), onChange: e => setProvider(e.target.value) }, providerOptions.map(option => (React.createElement(MenuItem, { key: option.value, value: option.value },
98
100
  React.createElement(Box, null,
99
101
  React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 } },
100
102
  option.label,
101
- option.apiKeyRequirement === 'required' && (React.createElement(Chip, { size: "small", label: "API Key", color: "default", variant: "outlined" }))),
103
+ option.apiKeyRequirement === 'required' && (React.createElement(Chip, { size: "small", label: trans.__('API Key'), color: "default", variant: "outlined" }))),
102
104
  option.description && (React.createElement(Typography, { variant: "caption", color: "text.secondary" }, option.description)))))))),
103
- selectedProvider?.allowCustomModel ? (React.createElement(TextField, { fullWidth: true, label: "Model", value: model, onChange: e => setModel(e.target.value), placeholder: "Enter model name", helperText: "Enter any compatible model name", required: true })) : (React.createElement(FormControl, { fullWidth: true, required: true },
104
- React.createElement(InputLabel, null, "Model"),
105
- React.createElement(Select, { value: model, label: "Model", onChange: e => setModel(e.target.value) }, selectedProvider?.models.map(modelOption => (React.createElement(MenuItem, { key: modelOption, value: modelOption },
105
+ selectedProvider?.allowCustomModel ? (React.createElement(TextField, { fullWidth: true, label: trans.__('Model'), value: model, onChange: e => setModel(e.target.value), placeholder: trans.__('Enter model name'), helperText: trans.__('Enter any compatible model name'), required: true })) : (React.createElement(FormControl, { fullWidth: true, required: true },
106
+ React.createElement(InputLabel, null, trans.__('Model')),
107
+ React.createElement(Select, { value: model, label: trans.__('Model'), onChange: e => setModel(e.target.value) }, selectedProvider?.models.map(modelOption => (React.createElement(MenuItem, { key: modelOption, value: modelOption },
106
108
  React.createElement(Box, null,
107
109
  React.createElement(Typography, { variant: "body1" }, modelOption),
108
110
  React.createElement(Typography, { variant: "caption", color: "text.secondary" }, modelOption.includes('sonnet')
109
- ? 'Balanced performance'
111
+ ? trans.__('Balanced performance')
110
112
  : modelOption.includes('opus')
111
- ? 'Advanced reasoning'
113
+ ? trans.__('Advanced reasoning')
112
114
  : modelOption.includes('haiku')
113
- ? 'Fast and lightweight'
115
+ ? trans.__('Fast and lightweight')
114
116
  : modelOption.includes('large')
115
- ? 'Most capable model'
117
+ ? trans.__('Most capable model')
116
118
  : modelOption.includes('small')
117
- ? 'Fast and efficient'
119
+ ? trans.__('Fast and efficient')
118
120
  : modelOption.includes('codestral')
119
- ? 'Code-specialized'
120
- : 'General purpose')))))))),
121
+ ? trans.__('Code-specialized')
122
+ : trans.__('General purpose'))))))))),
121
123
  selectedProvider &&
122
124
  selectedProvider?.apiKeyRequirement !== 'none' && (React.createElement(TextField, { fullWidth: true, inputRef: apiKeyRef, label: selectedProvider?.apiKeyRequirement === 'required'
123
- ? 'API Key'
124
- : 'API Key (Optional)', type: showApiKey ? 'text' : 'password', value: apiKey, onChange: e => setApiKey(e.target.value), placeholder: "Enter your API key...", required: selectedProvider?.apiKeyRequirement === 'required', InputProps: {
125
+ ? trans.__('API Key')
126
+ : trans.__('API Key (Optional)'), type: showApiKey ? 'text' : 'password', value: apiKey, onChange: e => setApiKey(e.target.value), placeholder: trans.__('Enter your API key...'), required: selectedProvider?.apiKeyRequirement === 'required', InputProps: {
125
127
  endAdornment: (React.createElement(InputAdornment, { position: "end" },
126
128
  React.createElement(IconButton, { onClick: () => setShowApiKey(!showApiKey), edge: "end" }, showApiKey ? React.createElement(VisibilityOff, null) : React.createElement(Visibility, null))))
127
129
  } })),
@@ -135,7 +137,7 @@ export const ProviderConfigDialog = ({ open, onClose, onSave, initialConfig, mod
135
137
  React.createElement(Box, null,
136
138
  React.createElement(Typography, { variant: "body2" }, option),
137
139
  urlOption?.description && (React.createElement(Typography, { variant: "caption", color: "text.secondary" }, urlOption.description)))));
138
- }, renderInput: params => (React.createElement(TextField, { ...params, fullWidth: true, label: "Base URL", placeholder: "https://api.example.com/v1", onChange: e => setBaseURL(e.target.value) })), clearOnBlur: false })),
140
+ }, renderInput: params => (React.createElement(TextField, { ...params, fullWidth: true, label: trans.__('Base URL'), placeholder: "https://api.example.com/v1", onChange: e => setBaseURL(e.target.value) })), clearOnBlur: false })),
139
141
  React.createElement(Accordion, { expanded: expandedAdvanced, onChange: (_, isExpanded) => setExpandedAdvanced(isExpanded), sx: {
140
142
  mt: 2,
141
143
  bgcolor: 'transparent',
@@ -145,40 +147,38 @@ export const ProviderConfigDialog = ({ open, onClose, onSave, initialConfig, mod
145
147
  borderRadius: 1
146
148
  } },
147
149
  React.createElement(AccordionSummary, { expandIcon: React.createElement(ExpandMore, null) },
148
- React.createElement(Typography, { variant: "subtitle1", fontWeight: "medium" }, "Advanced Settings")),
150
+ React.createElement(Typography, { variant: "subtitle1", fontWeight: "medium" }, trans.__('Advanced Settings'))),
149
151
  React.createElement(AccordionDetails, { sx: { bgcolor: 'transparent' } },
150
152
  React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 } },
151
153
  React.createElement(Box, null,
152
- React.createElement(Typography, { gutterBottom: true },
153
- "Temperature: ",
154
- parameters.temperature ?? 'Default'),
154
+ React.createElement(Typography, { gutterBottom: true }, trans.__('Temperature: %1', parameters.temperature ?? trans.__('Default'))),
155
155
  React.createElement(Slider, { value: parameters.temperature ?? DEFAULT_TEMPERATURE, onChange: (_, value) => setParameters({
156
156
  ...parameters,
157
157
  temperature: value
158
158
  }), min: 0, max: 2, step: 0.1, valueLabelDisplay: "auto" }),
159
- React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Temperature for the model (lower values are more deterministic)")),
160
- React.createElement(TextField, { fullWidth: true, label: "Max Tokens (Optional)", type: "number", value: parameters.maxTokens ?? '', onChange: e => setParameters({
159
+ React.createElement(Typography, { variant: "caption", color: "text.secondary" }, trans.__('Temperature for the model (lower values are more deterministic)'))),
160
+ React.createElement(TextField, { fullWidth: true, label: trans.__('Max Tokens (Optional)'), type: "number", value: parameters.maxOutputTokens ?? '', onChange: e => setParameters({
161
161
  ...parameters,
162
- maxTokens: e.target.value
162
+ maxOutputTokens: e.target.value
163
163
  ? Number(e.target.value)
164
164
  : undefined
165
- }), placeholder: "Leave empty for provider default", helperText: "Maximum length of AI responses", inputProps: { min: 1 } }),
166
- React.createElement(TextField, { fullWidth: true, label: "Max Turns (Optional)", type: "number", value: parameters.maxTurns ?? '', onChange: e => setParameters({
165
+ }), placeholder: trans.__('Leave empty for provider default'), helperText: trans.__('Maximum length of AI responses'), inputProps: { min: 1 } }),
166
+ React.createElement(TextField, { fullWidth: true, label: trans.__('Max Turns (Optional)'), type: "number", value: parameters.maxTurns ?? '', onChange: e => setParameters({
167
167
  ...parameters,
168
168
  maxTurns: e.target.value
169
169
  ? Number(e.target.value)
170
170
  : undefined
171
- }), placeholder: `Default: ${DEFAULT_MAX_TURNS}`, helperText: "Maximum number of tool execution turns", inputProps: { min: 1, max: 100 } }),
172
- React.createElement(Typography, { variant: "body2", color: "text.secondary", sx: { mt: 2, mb: 1 } }, "Completion Options"),
171
+ }), placeholder: trans.__('Default: %1', DEFAULT_MAX_TURNS), helperText: trans.__('Maximum number of tool execution turns'), inputProps: { min: 1, max: 100 } }),
172
+ React.createElement(Typography, { variant: "body2", color: "text.secondary", sx: { mt: 2, mb: 1 } }, trans.__('Completion Options')),
173
173
  React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: parameters.supportsFillInMiddle ?? false, onChange: e => setParameters({
174
174
  ...parameters,
175
175
  supportsFillInMiddle: e.target.checked
176
- }) }), label: "Fill-in-the-middle support" }),
176
+ }) }), label: trans.__('Fill-in-the-middle support') }),
177
177
  React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: parameters.useFilterText ?? false, onChange: e => setParameters({
178
178
  ...parameters,
179
179
  useFilterText: e.target.checked
180
- }) }), label: "Use filter text" })))))),
180
+ }) }), label: trans.__('Use filter text') })))))),
181
181
  React.createElement(DialogActions, null,
182
- React.createElement(Button, { onClick: onClose }, "Cancel"),
183
- React.createElement(Button, { onClick: handleSave, variant: "contained", disabled: !isValid }, mode === 'add' ? 'Add Provider' : 'Save Changes'))));
182
+ React.createElement(Button, { onClick: onClose }, trans.__('Cancel')),
183
+ React.createElement(Button, { onClick: handleSave, variant: "contained", disabled: !isValid }, mode === 'add' ? trans.__('Add Provider') : trans.__('Save Changes')))));
184
184
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupyterlite/ai",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "AI code completions and chat for JupyterLite",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -51,14 +51,17 @@
51
51
  "stylelint:check": "stylelint --cache \"style/**/*.css\"",
52
52
  "watch": "run-p watch:src watch:labextension",
53
53
  "watch:src": "tsc -w --sourceMap",
54
- "watch:labextension": "jupyter labextension watch ."
54
+ "watch:labextension": "jupyter labextension watch .",
55
+ "docs": "jupyter book start",
56
+ "docs:build": "sed -e 's/\\[@/[/g' -e 's/@/\\&#64;/g' CHANGELOG.md > docs/_changelog_content.md && jupyter book build --html"
55
57
  },
56
58
  "dependencies": {
57
- "@ai-sdk/anthropic": "^2.0.30",
58
- "@ai-sdk/google": "^2.0.19",
59
- "@ai-sdk/mistral": "^2.0.17",
60
- "@ai-sdk/openai": "^2.0.44",
61
- "@ai-sdk/openai-compatible": "^1.0.26",
59
+ "@ai-sdk/anthropic": "^3.0.1",
60
+ "@ai-sdk/google": "^3.0.1",
61
+ "@ai-sdk/mcp": "^1.0.1",
62
+ "@ai-sdk/mistral": "^3.0.1",
63
+ "@ai-sdk/openai": "^3.0.1",
64
+ "@ai-sdk/openai-compatible": "^2.0.1",
62
65
  "@jupyter/chat": "^0.18.2",
63
66
  "@jupyterlab/application": "^4.0.0",
64
67
  "@jupyterlab/apputils": "^4.5.6",
@@ -81,14 +84,11 @@
81
84
  "@lumino/polling": "^2.1.4",
82
85
  "@lumino/signaling": "^2.1.4",
83
86
  "@lumino/widgets": "^2.7.1",
84
- "@modelcontextprotocol/sdk": "^1.19.1",
85
87
  "@mui/icons-material": "^7",
86
88
  "@mui/material": "^7",
87
- "@openai/agents": "^0.1.9",
88
- "@openai/agents-extensions": "^0.1.5",
89
- "ai": "^5.0.60",
89
+ "ai": "^6.0.0",
90
90
  "jupyter-secrets-manager": "^0.4.0",
91
- "zod": "^3.25.76"
91
+ "zod": "^4.2.1"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@jupyterlab/builder": "^4.0.0",