@jupyterlite/ai 0.18.0 → 0.19.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 (108) hide show
  1. package/lib/chat-commands/clear.d.ts +1 -0
  2. package/lib/chat-commands/index.d.ts +1 -0
  3. package/lib/chat-commands/skills.d.ts +2 -1
  4. package/lib/chat-model-handler.d.ts +3 -1
  5. package/lib/chat-model.d.ts +46 -8
  6. package/lib/chat-model.js +51 -21
  7. package/lib/completion/completion-provider.d.ts +3 -1
  8. package/lib/completion/completion-provider.js +1 -2
  9. package/lib/completion/index.d.ts +1 -0
  10. package/lib/components/clear-button.d.ts +1 -0
  11. package/lib/components/clear-button.js +3 -4
  12. package/lib/components/completion-status.d.ts +1 -0
  13. package/lib/components/completion-status.js +5 -4
  14. package/lib/components/index.d.ts +1 -0
  15. package/lib/components/model-select.d.ts +1 -0
  16. package/lib/components/model-select.js +62 -67
  17. package/lib/components/save-button.d.ts +1 -0
  18. package/lib/components/save-button.js +4 -5
  19. package/lib/components/stop-button.d.ts +1 -0
  20. package/lib/components/stop-button.js +3 -4
  21. package/lib/components/tool-select.d.ts +3 -1
  22. package/lib/components/tool-select.js +47 -60
  23. package/lib/components/usage-display.d.ts +4 -2
  24. package/lib/components/usage-display.js +50 -61
  25. package/lib/diff-manager.d.ts +3 -1
  26. package/lib/index.d.ts +3 -2
  27. package/lib/index.js +28 -17
  28. package/lib/models/settings-model.d.ts +3 -1
  29. package/lib/rendered-message-outputarea.d.ts +1 -0
  30. package/lib/tokens.d.ts +18 -640
  31. package/lib/tokens.js +2 -31
  32. package/lib/widgets/ai-settings.d.ts +3 -1
  33. package/lib/widgets/ai-settings.js +185 -349
  34. package/lib/widgets/main-area-chat.d.ts +1 -0
  35. package/lib/widgets/provider-config-dialog.d.ts +2 -1
  36. package/lib/widgets/provider-config-dialog.js +102 -167
  37. package/package.json +111 -258
  38. package/src/chat-commands/skills.ts +2 -2
  39. package/src/chat-model-handler.ts +6 -4
  40. package/src/chat-model.ts +66 -19
  41. package/src/completion/completion-provider.ts +6 -6
  42. package/src/components/clear-button.tsx +0 -2
  43. package/src/components/completion-status.tsx +2 -2
  44. package/src/components/model-select.tsx +1 -1
  45. package/src/components/stop-button.tsx +0 -2
  46. package/src/components/tool-select.tsx +10 -9
  47. package/src/components/usage-display.tsx +4 -2
  48. package/src/diff-manager.ts +4 -3
  49. package/src/index.ts +62 -44
  50. package/src/models/settings-model.ts +6 -6
  51. package/src/tokens.ts +23 -788
  52. package/src/widgets/ai-settings.tsx +14 -11
  53. package/src/widgets/provider-config-dialog.tsx +8 -8
  54. package/LICENSE +0 -30
  55. package/README.md +0 -49
  56. package/lib/agent.d.ts +0 -280
  57. package/lib/agent.js +0 -1103
  58. package/lib/icons.d.ts +0 -3
  59. package/lib/icons.js +0 -8
  60. package/lib/providers/built-in-providers.d.ts +0 -21
  61. package/lib/providers/built-in-providers.js +0 -233
  62. package/lib/providers/generated-model-info.d.ts +0 -8
  63. package/lib/providers/generated-model-info.js +0 -502
  64. package/lib/providers/model-info.d.ts +0 -6
  65. package/lib/providers/model-info.js +0 -91
  66. package/lib/providers/models.d.ts +0 -37
  67. package/lib/providers/models.js +0 -28
  68. package/lib/providers/provider-registry.d.ts +0 -49
  69. package/lib/providers/provider-registry.js +0 -72
  70. package/lib/providers/provider-tools.d.ts +0 -36
  71. package/lib/providers/provider-tools.js +0 -93
  72. package/lib/skills/index.d.ts +0 -4
  73. package/lib/skills/index.js +0 -7
  74. package/lib/skills/parse-skill.d.ts +0 -25
  75. package/lib/skills/parse-skill.js +0 -69
  76. package/lib/skills/skill-loader.d.ts +0 -25
  77. package/lib/skills/skill-loader.js +0 -133
  78. package/lib/skills/skill-registry.d.ts +0 -31
  79. package/lib/skills/skill-registry.js +0 -100
  80. package/lib/skills/types.d.ts +0 -29
  81. package/lib/skills/types.js +0 -5
  82. package/lib/tools/commands.d.ts +0 -11
  83. package/lib/tools/commands.js +0 -154
  84. package/lib/tools/skills.d.ts +0 -9
  85. package/lib/tools/skills.js +0 -73
  86. package/lib/tools/tool-registry.d.ts +0 -35
  87. package/lib/tools/tool-registry.js +0 -55
  88. package/lib/tools/web.d.ts +0 -8
  89. package/lib/tools/web.js +0 -196
  90. package/src/agent.ts +0 -1431
  91. package/src/icons.ts +0 -11
  92. package/src/providers/built-in-providers.ts +0 -241
  93. package/src/providers/generated-model-info.ts +0 -508
  94. package/src/providers/model-info.ts +0 -145
  95. package/src/providers/models.ts +0 -76
  96. package/src/providers/provider-registry.ts +0 -88
  97. package/src/providers/provider-tools.ts +0 -179
  98. package/src/skills/index.ts +0 -14
  99. package/src/skills/parse-skill.ts +0 -91
  100. package/src/skills/skill-loader.ts +0 -175
  101. package/src/skills/skill-registry.ts +0 -137
  102. package/src/skills/types.ts +0 -37
  103. package/src/tools/commands.ts +0 -210
  104. package/src/tools/skills.ts +0 -84
  105. package/src/tools/tool-registry.ts +0 -63
  106. package/src/tools/web.ts +0 -238
  107. package/src/types.d.ts +0 -4
  108. package/style/icons/jupyternaut-lite.svg +0 -7
@@ -28,3 +28,4 @@ export declare class MainAreaChat extends MainAreaWidget<ChatWidget> {
28
28
  private _titleChanged;
29
29
  private _outputAreaCompat;
30
30
  }
31
+ //# sourceMappingURL=main-area-chat.d.ts.map
@@ -1,6 +1,6 @@
1
+ import type { IProviderConfig, IProviderRegistry } from '@jupyternaut/agent';
1
2
  import type { TranslationBundle } from '@jupyterlab/translation';
2
3
  import React from 'react';
3
- import type { IProviderConfig, IProviderRegistry } from '../tokens';
4
4
  interface IProviderConfigDialogProps {
5
5
  open: boolean;
6
6
  onClose: () => void;
@@ -13,3 +13,4 @@ interface IProviderConfigDialogProps {
13
13
  }
14
14
  export declare const ProviderConfigDialog: React.FC<IProviderConfigDialogProps>;
15
15
  export {};
16
+ //# sourceMappingURL=provider-config-dialog.d.ts.map
@@ -1,10 +1,12 @@
1
+ import { createElement as _createElement } from "react";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { getProviderModelInfo } from '@jupyternaut/agent';
1
4
  import ExpandMore from '@mui/icons-material/ExpandMore';
2
5
  import Delete from '@mui/icons-material/Delete';
3
6
  import Visibility from '@mui/icons-material/Visibility';
4
7
  import VisibilityOff from '@mui/icons-material/VisibilityOff';
5
8
  import { Accordion, AccordionDetails, AccordionSummary, Autocomplete, Box, Button, Chip, Dialog, DialogActions, DialogContent, DialogTitle, FormControl, FormControlLabel, IconButton, InputAdornment, InputLabel, List, ListItem, ListItemText, MenuItem, Select, Slider, Switch, TextField, Typography } from '@mui/material';
6
9
  import React from 'react';
7
- import { getProviderModelInfo } from '../providers/model-info';
8
10
  /**
9
11
  * Default parameter values for provider configuration
10
12
  */
@@ -188,32 +190,26 @@ export const ProviderConfigDialog = ({ open, onClose, onSave, initialConfig, mod
188
190
  }, [customSettings, updateCustomSetting]);
189
191
  const renderDomainList = React.useCallback((fieldId, label, placeholder, values) => {
190
192
  const domainValues = toStringArray(values);
191
- return (React.createElement(Box, null,
192
- React.createElement(Typography, { variant: "body2", gutterBottom: true }, label),
193
- React.createElement(List, { dense: true, sx: {
194
- mb: 1,
195
- maxHeight: 160,
196
- overflow: 'auto',
197
- border: 1,
198
- borderColor: 'divider',
199
- borderRadius: 1
200
- } }, domainValues.length === 0 ? (React.createElement(ListItem, null,
201
- React.createElement(ListItemText, { secondary: trans.__('No domains added.'), slotProps: {
202
- secondary: {
203
- color: 'text.secondary'
193
+ return (_jsxs(Box, { children: [_jsx(Typography, { variant: "body2", gutterBottom: true, children: label }), _jsx(List, { dense: true, sx: {
194
+ mb: 1,
195
+ maxHeight: 160,
196
+ overflow: 'auto',
197
+ border: 1,
198
+ borderColor: 'divider',
199
+ borderRadius: 1
200
+ }, children: domainValues.length === 0 ? (_jsx(ListItem, { children: _jsx(ListItemText, { secondary: trans.__('No domains added.'), slotProps: {
201
+ secondary: {
202
+ color: 'text.secondary'
203
+ }
204
+ } }) })) : (domainValues.map(value => (_jsx(ListItem, { secondaryAction: _jsx(IconButton, { onClick: () => removeDomainValue(fieldId, value), size: "small", children: _jsx(Delete, { fontSize: "small" }) }), children: _jsx(ListItemText, { primary: value }) }, value)))) }), _jsx(TextField, { fullWidth: true, size: "small", label: trans.__('Add Domain'), value: domainInputs[fieldId], onChange: e => setDomainInputs(prev => ({
205
+ ...prev,
206
+ [fieldId]: e.target.value
207
+ })), onKeyDown: e => {
208
+ if (e.key === 'Enter') {
209
+ e.preventDefault();
210
+ addDomainValue(fieldId);
204
211
  }
205
- } }))) : (domainValues.map(value => (React.createElement(ListItem, { key: value, secondaryAction: React.createElement(IconButton, { onClick: () => removeDomainValue(fieldId, value), size: "small" },
206
- React.createElement(Delete, { fontSize: "small" })) },
207
- React.createElement(ListItemText, { primary: value })))))),
208
- React.createElement(TextField, { fullWidth: true, size: "small", label: trans.__('Add Domain'), value: domainInputs[fieldId], onChange: e => setDomainInputs(prev => ({
209
- ...prev,
210
- [fieldId]: e.target.value
211
- })), onKeyDown: e => {
212
- if (e.key === 'Enter') {
213
- e.preventDefault();
214
- addDomainValue(fieldId);
215
- }
216
- }, placeholder: placeholder, helperText: trans.__('Press Enter to add one domain.') })));
212
+ }, placeholder: placeholder, helperText: trans.__('Press Enter to add one domain.') })] }));
217
213
  }, [addDomainValue, domainInputs, removeDomainValue, trans]);
218
214
  const handleSave = () => {
219
215
  if (!name.trim() || !provider || !model) {
@@ -240,145 +236,84 @@ export const ProviderConfigDialog = ({ open, onClose, onSave, initialConfig, mod
240
236
  provider &&
241
237
  model &&
242
238
  (selectedProvider?.apiKeyRequirement !== 'required' || apiKey);
243
- return (React.createElement(Dialog, { open: open, onClose: onClose, maxWidth: "md", fullWidth: true },
244
- React.createElement(DialogTitle, null, mode === 'add'
245
- ? trans.__('Add New Provider')
246
- : trans.__('Edit Provider')),
247
- React.createElement(DialogContent, null,
248
- React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2, pt: 1 } },
249
- 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 }),
250
- React.createElement(FormControl, { fullWidth: true, required: true },
251
- React.createElement(InputLabel, null, trans.__('Provider Type')),
252
- React.createElement(Select, { value: provider, label: trans.__('Provider Type'), onChange: e => handleProviderChange(e.target.value) }, providerOptions.map(option => (React.createElement(MenuItem, { key: option.value, value: option.value },
253
- React.createElement(Box, null,
254
- React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 } },
255
- option.label,
256
- option.apiKeyRequirement === 'required' && (React.createElement(Chip, { size: "small", label: trans.__('API Key'), color: "default", variant: "outlined" }))),
257
- option.description && (React.createElement(Typography, { variant: "caption", color: "text.secondary" }, option.description)))))))),
258
- React.createElement(Autocomplete, { freeSolo: true, fullWidth: true, options: selectedProvider?.models ?? [], value: model, onChange: (_, value) => {
259
- setModel(typeof value === 'string' ? value : '');
260
- }, inputValue: model, onInputChange: (_, value) => {
261
- setModel(value);
262
- }, renderInput: params => (React.createElement(TextField, { ...params, fullWidth: true, label: trans.__('Model'), placeholder: trans.__('Select or type a model ID'), required: true, helperText: trans.__('Choose from the list or enter a custom model ID') })), clearOnBlur: false }),
263
- selectedProvider &&
264
- selectedProvider?.apiKeyRequirement !== 'none' && (React.createElement(TextField, { fullWidth: true, inputRef: handleRef, label: selectedProvider?.apiKeyRequirement === 'required'
265
- ? trans.__('API Key')
266
- : 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: {
267
- endAdornment: (React.createElement(InputAdornment, { position: "end" },
268
- React.createElement(IconButton, { onClick: () => setShowApiKey(!showApiKey), edge: "end" }, showApiKey ? React.createElement(VisibilityOff, null) : React.createElement(Visibility, null))))
269
- } })),
270
- selectedProvider?.supportsBaseURL && (React.createElement(Autocomplete, { freeSolo: true, fullWidth: true, options: (selectedProvider.baseUrls ?? []).map(option => option.url), value: baseURL || '', onChange: (_, value) => {
271
- if (value && typeof value === 'string') {
272
- setBaseURL(value);
273
- }
274
- }, inputValue: baseURL || '', renderOption: (props, option) => {
275
- const urlOption = (selectedProvider.baseUrls ?? []).find(u => u.url === option);
276
- return (React.createElement(Box, { component: "li", ...props, key: option },
277
- React.createElement(Box, null,
278
- React.createElement(Typography, { variant: "body2" }, option),
279
- urlOption?.description && (React.createElement(Typography, { variant: "caption", color: "text.secondary" }, urlOption.description)))));
280
- }, 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 })),
281
- React.createElement(Accordion, { expanded: expandedAdvanced, onChange: (_, isExpanded) => setExpandedAdvanced(isExpanded), sx: {
282
- mt: 2,
283
- bgcolor: 'transparent',
284
- boxShadow: 'none',
285
- border: 1,
286
- borderColor: 'divider',
287
- borderRadius: 1
288
- } },
289
- React.createElement(AccordionSummary, { expandIcon: React.createElement(ExpandMore, null) },
290
- React.createElement(Typography, { variant: "subtitle1", fontWeight: "medium" }, trans.__('Advanced Settings'))),
291
- React.createElement(AccordionDetails, { sx: { bgcolor: 'transparent' } },
292
- React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 } },
293
- React.createElement(Box, null,
294
- React.createElement(Typography, { gutterBottom: true }, trans.__('Temperature: %1', parameters.temperature ?? trans.__('Default'))),
295
- React.createElement(Slider, { value: parameters.temperature ?? DEFAULT_TEMPERATURE, onChange: (_, value) => setParameters({
296
- ...parameters,
297
- temperature: value
298
- }), min: 0, max: 2, step: 0.1, valueLabelDisplay: "auto" }),
299
- React.createElement(Typography, { variant: "caption", color: "text.secondary" }, trans.__('Temperature for the model (lower values are more deterministic)'))),
300
- React.createElement(TextField, { fullWidth: true, label: trans.__('Max Tokens (Optional)'), type: "number", value: parameters.maxOutputTokens ?? '', onChange: e => setParameters({
301
- ...parameters,
302
- maxOutputTokens: e.target.value
303
- ? Number(e.target.value)
304
- : undefined
305
- }), placeholder: trans.__('Leave empty for provider default'), helperText: trans.__('Maximum length of AI responses'), slotProps: { htmlInput: { min: 1 } } }),
306
- React.createElement(TextField, { fullWidth: true, label: trans.__('Max Turns (Optional)'), type: "number", value: parameters.maxTurns ?? '', onChange: e => setParameters({
307
- ...parameters,
308
- maxTurns: e.target.value
309
- ? Number(e.target.value)
310
- : undefined
311
- }), placeholder: trans.__('Default: %1', DEFAULT_MAX_TURNS), helperText: trans.__('Maximum number of tool execution turns'), slotProps: { htmlInput: { min: 1, max: 100 } } }),
312
- React.createElement(TextField, { fullWidth: true, label: trans.__('Context Window (Optional)'), type: "number", value: parameters.contextWindow ?? '', onChange: e => setParameters({
313
- ...parameters,
314
- contextWindow: e.target.value
315
- ? Number(e.target.value)
316
- : undefined
317
- }), placeholder: selectedModelInfo?.contextWindow !== undefined
318
- ? trans.__('Default: %1', selectedModelInfo.contextWindow.toLocaleString())
319
- : trans.__('e.g., 128000'), helperText: selectedModelInfo?.contextWindow !== undefined &&
320
- parameters.contextWindow === undefined
321
- ? trans.__('Using provider metadata default of %1 tokens for this model unless you override it here.', selectedModelInfo.contextWindow.toLocaleString())
322
- : trans.__('Model context window size in tokens (used for context usage estimation)'), slotProps: { htmlInput: { min: 1 } } }),
323
- React.createElement(Typography, { variant: "body2", color: "text.secondary", sx: { mt: 2, mb: 1 } }, trans.__('Completion Options')),
324
- React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: parameters.supportsFillInMiddle ?? false, onChange: e => setParameters({
325
- ...parameters,
326
- supportsFillInMiddle: e.target.checked
327
- }) }), label: trans.__('Fill-in-the-middle support') }),
328
- React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: parameters.useFilterText ?? false, onChange: e => setParameters({
329
- ...parameters,
330
- useFilterText: e.target.checked
331
- }) }), label: trans.__('Use filter text') }),
332
- (supportsWebSearch || supportsWebFetch) && (React.createElement(React.Fragment, null,
333
- React.createElement(Typography, { variant: "body2", color: "text.secondary", sx: { mt: 2, mb: 1 } }, trans.__('Provider Web Tools')),
334
- supportsWebSearch && (React.createElement(React.Fragment, null,
335
- React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: webSearchSettings.enabled === true, onChange: e => updateCustomSetting('webSearch', 'enabled', e.target.checked) }), label: trans.__('Enable Web Search') }),
336
- webSearchSettings.enabled === true && (React.createElement(Box, { sx: {
337
- pl: 2,
338
- borderLeft: 2,
339
- borderColor: 'divider',
340
- display: 'flex',
341
- flexDirection: 'column',
342
- gap: 1.5
343
- } },
344
- (webSearchImplementation === 'openai' ||
345
- webSearchImplementation === 'anthropic') &&
346
- renderDomainList('webSearch.allowedDomains', trans.__('Allowed Domains'), trans.__('example.com'), webSearchSettings.allowedDomains),
347
- webSearchImplementation === 'openai' && (React.createElement(React.Fragment, null,
348
- React.createElement(FormControl, { fullWidth: true },
349
- React.createElement(InputLabel, null, trans.__('Search Context Size')),
350
- React.createElement(Select, { value: webSearchSettings.searchContextSize ??
351
- 'medium', label: trans.__('Search Context Size'), onChange: e => updateCustomSetting('webSearch', 'searchContextSize', e.target.value) },
352
- React.createElement(MenuItem, { value: "low" }, trans.__('Low')),
353
- React.createElement(MenuItem, { value: "medium" }, trans.__('Medium')),
354
- React.createElement(MenuItem, { value: "high" }, trans.__('High')))),
355
- React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: webSearchSettings.externalWebAccess !==
356
- false, onChange: e => updateCustomSetting('webSearch', 'externalWebAccess', e.target.checked) }), label: trans.__('Use External Web Access') }))),
357
- webSearchImplementation === 'anthropic' && (React.createElement(React.Fragment, null,
358
- React.createElement(TextField, { fullWidth: true, label: trans.__('Web Search Max Uses'), type: "number", value: webSearchSettings.maxUses ?? '', onChange: e => updateCustomSetting('webSearch', 'maxUses', e.target.value
359
- ? Number(e.target.value)
360
- : undefined), slotProps: { htmlInput: { min: 1 } } }),
361
- renderDomainList('webSearch.blockedDomains', trans.__('Blocked Domains'), trans.__('spam.example.com'), webSearchSettings.blockedDomains))))))),
362
- supportsWebFetch && (React.createElement(React.Fragment, null,
363
- React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: webFetchSettings.enabled === true, onChange: e => updateCustomSetting('webFetch', 'enabled', e.target.checked) }), label: trans.__('Enable Web Fetch') }),
364
- webFetchSettings.enabled === true && (React.createElement(Box, { sx: {
365
- pl: 2,
366
- borderLeft: 2,
367
- borderColor: 'divider',
368
- display: 'flex',
369
- flexDirection: 'column',
370
- gap: 1.5
371
- } },
372
- React.createElement(TextField, { fullWidth: true, label: trans.__('Web Fetch Max Uses'), type: "number", value: webFetchSettings.maxUses ?? '', onChange: e => updateCustomSetting('webFetch', 'maxUses', e.target.value
373
- ? Number(e.target.value)
374
- : undefined), slotProps: { htmlInput: { min: 1 } } }),
375
- React.createElement(TextField, { fullWidth: true, label: trans.__('Web Fetch Max Content Tokens'), type: "number", value: webFetchSettings.maxContentTokens ?? '', onChange: e => updateCustomSetting('webFetch', 'maxContentTokens', e.target.value
376
- ? Number(e.target.value)
377
- : undefined), slotProps: { htmlInput: { min: 1 } } }),
378
- renderDomainList('webFetch.allowedDomains', trans.__('Allowed Domains'), trans.__('docs.example.com'), webFetchSettings.allowedDomains),
379
- renderDomainList('webFetch.blockedDomains', trans.__('Blocked Domains'), trans.__('spam.example.com'), webFetchSettings.blockedDomains),
380
- React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: webFetchSettings.citationsEnabled === true, onChange: e => updateCustomSetting('webFetch', 'citationsEnabled', e.target.checked) }), label: trans.__('Enable Citations') })))))))))))),
381
- React.createElement(DialogActions, null,
382
- React.createElement(Button, { onClick: onClose }, trans.__('Cancel')),
383
- React.createElement(Button, { onClick: handleSave, variant: "contained", disabled: !isValid }, mode === 'add' ? trans.__('Add Provider') : trans.__('Save Changes')))));
239
+ return (_jsxs(Dialog, { open: open, onClose: onClose, maxWidth: "md", fullWidth: true, children: [_jsx(DialogTitle, { children: mode === 'add'
240
+ ? trans.__('Add New Provider')
241
+ : trans.__('Edit Provider') }), _jsx(DialogContent, { children: _jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2, pt: 1 }, children: [_jsx(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 }), _jsxs(FormControl, { fullWidth: true, required: true, children: [_jsx(InputLabel, { children: trans.__('Provider Type') }), _jsx(Select, { value: provider, label: trans.__('Provider Type'), onChange: e => handleProviderChange(e.target.value), children: providerOptions.map(option => (_jsx(MenuItem, { value: option.value, children: _jsxs(Box, { children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [option.label, option.apiKeyRequirement === 'required' && (_jsx(Chip, { size: "small", label: trans.__('API Key'), color: "default", variant: "outlined" }))] }), option.description && (_jsx(Typography, { variant: "caption", color: "text.secondary", children: option.description }))] }) }, option.value))) })] }), _jsx(Autocomplete, { freeSolo: true, fullWidth: true, options: selectedProvider?.models ?? [], value: model, onChange: (_, value) => {
242
+ setModel(typeof value === 'string' ? value : '');
243
+ }, inputValue: model, onInputChange: (_, value) => {
244
+ setModel(value);
245
+ }, renderInput: params => (_jsx(TextField, { ...params, fullWidth: true, label: trans.__('Model'), placeholder: trans.__('Select or type a model ID'), required: true, helperText: trans.__('Choose from the list or enter a custom model ID') })), clearOnBlur: false }), selectedProvider &&
246
+ selectedProvider?.apiKeyRequirement !== 'none' && (_jsx(TextField, { fullWidth: true, inputRef: handleRef, label: selectedProvider?.apiKeyRequirement === 'required'
247
+ ? trans.__('API Key')
248
+ : 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: {
249
+ endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { onClick: () => setShowApiKey(!showApiKey), edge: "end", children: showApiKey ? _jsx(VisibilityOff, {}) : _jsx(Visibility, {}) }) }))
250
+ } })), selectedProvider?.supportsBaseURL && (_jsx(Autocomplete, { freeSolo: true, fullWidth: true, options: (selectedProvider.baseUrls ?? []).map(option => option.url), value: baseURL || '', onChange: (_, value) => {
251
+ if (value && typeof value === 'string') {
252
+ setBaseURL(value);
253
+ }
254
+ }, inputValue: baseURL || '', renderOption: (props, option) => {
255
+ const urlOption = (selectedProvider.baseUrls ?? []).find(u => u.url === option);
256
+ return (_createElement(Box, { component: "li", ...props, key: option },
257
+ _jsxs(Box, { children: [_jsx(Typography, { variant: "body2", children: option }), urlOption?.description && (_jsx(Typography, { variant: "caption", color: "text.secondary", children: urlOption.description }))] })));
258
+ }, renderInput: params => (_jsx(TextField, { ...params, fullWidth: true, label: trans.__('Base URL'), placeholder: "https://api.example.com/v1", onChange: e => setBaseURL(e.target.value) })), clearOnBlur: false })), _jsxs(Accordion, { expanded: expandedAdvanced, onChange: (_, isExpanded) => setExpandedAdvanced(isExpanded), sx: {
259
+ mt: 2,
260
+ bgcolor: 'transparent',
261
+ boxShadow: 'none',
262
+ border: 1,
263
+ borderColor: 'divider',
264
+ borderRadius: 1
265
+ }, children: [_jsx(AccordionSummary, { expandIcon: _jsx(ExpandMore, {}), children: _jsx(Typography, { variant: "subtitle1", fontWeight: "medium", children: trans.__('Advanced Settings') }) }), _jsx(AccordionDetails, { sx: { bgcolor: 'transparent' }, children: _jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsxs(Box, { children: [_jsx(Typography, { gutterBottom: true, children: trans.__('Temperature: %1', parameters.temperature ?? trans.__('Default')) }), _jsx(Slider, { value: parameters.temperature ?? DEFAULT_TEMPERATURE, onChange: (_, value) => setParameters({
266
+ ...parameters,
267
+ temperature: value
268
+ }), min: 0, max: 2, step: 0.1, valueLabelDisplay: "auto" }), _jsx(Typography, { variant: "caption", color: "text.secondary", children: trans.__('Temperature for the model (lower values are more deterministic)') })] }), _jsx(TextField, { fullWidth: true, label: trans.__('Max Tokens (Optional)'), type: "number", value: parameters.maxOutputTokens ?? '', onChange: e => setParameters({
269
+ ...parameters,
270
+ maxOutputTokens: e.target.value
271
+ ? Number(e.target.value)
272
+ : undefined
273
+ }), placeholder: trans.__('Leave empty for provider default'), helperText: trans.__('Maximum length of AI responses'), slotProps: { htmlInput: { min: 1 } } }), _jsx(TextField, { fullWidth: true, label: trans.__('Max Turns (Optional)'), type: "number", value: parameters.maxTurns ?? '', onChange: e => setParameters({
274
+ ...parameters,
275
+ maxTurns: e.target.value
276
+ ? Number(e.target.value)
277
+ : undefined
278
+ }), placeholder: trans.__('Default: %1', DEFAULT_MAX_TURNS), helperText: trans.__('Maximum number of tool execution turns'), slotProps: { htmlInput: { min: 1, max: 100 } } }), _jsx(TextField, { fullWidth: true, label: trans.__('Context Window (Optional)'), type: "number", value: parameters.contextWindow ?? '', onChange: e => setParameters({
279
+ ...parameters,
280
+ contextWindow: e.target.value
281
+ ? Number(e.target.value)
282
+ : undefined
283
+ }), placeholder: selectedModelInfo?.contextWindow !== undefined
284
+ ? trans.__('Default: %1', selectedModelInfo.contextWindow.toLocaleString())
285
+ : trans.__('e.g., 128000'), helperText: selectedModelInfo?.contextWindow !== undefined &&
286
+ parameters.contextWindow === undefined
287
+ ? trans.__('Using provider metadata default of %1 tokens for this model unless you override it here.', selectedModelInfo.contextWindow.toLocaleString())
288
+ : trans.__('Model context window size in tokens (used for context usage estimation)'), slotProps: { htmlInput: { min: 1 } } }), _jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mt: 2, mb: 1 }, children: trans.__('Completion Options') }), _jsx(FormControlLabel, { control: _jsx(Switch, { checked: parameters.supportsFillInMiddle ?? false, onChange: e => setParameters({
289
+ ...parameters,
290
+ supportsFillInMiddle: e.target.checked
291
+ }) }), label: trans.__('Fill-in-the-middle support') }), _jsx(FormControlLabel, { control: _jsx(Switch, { checked: parameters.useFilterText ?? false, onChange: e => setParameters({
292
+ ...parameters,
293
+ useFilterText: e.target.checked
294
+ }) }), label: trans.__('Use filter text') }), (supportsWebSearch || supportsWebFetch) && (_jsxs(_Fragment, { children: [_jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mt: 2, mb: 1 }, children: trans.__('Provider Web Tools') }), supportsWebSearch && (_jsxs(_Fragment, { children: [_jsx(FormControlLabel, { control: _jsx(Switch, { checked: webSearchSettings.enabled === true, onChange: e => updateCustomSetting('webSearch', 'enabled', e.target.checked) }), label: trans.__('Enable Web Search') }), webSearchSettings.enabled === true && (_jsxs(Box, { sx: {
295
+ pl: 2,
296
+ borderLeft: 2,
297
+ borderColor: 'divider',
298
+ display: 'flex',
299
+ flexDirection: 'column',
300
+ gap: 1.5
301
+ }, children: [(webSearchImplementation === 'openai' ||
302
+ webSearchImplementation === 'anthropic') &&
303
+ renderDomainList('webSearch.allowedDomains', trans.__('Allowed Domains'), trans.__('example.com'), webSearchSettings.allowedDomains), webSearchImplementation === 'openai' && (_jsxs(_Fragment, { children: [_jsxs(FormControl, { fullWidth: true, children: [_jsx(InputLabel, { children: trans.__('Search Context Size') }), _jsxs(Select, { value: webSearchSettings.searchContextSize ??
304
+ 'medium', label: trans.__('Search Context Size'), onChange: e => updateCustomSetting('webSearch', 'searchContextSize', e.target.value), children: [_jsx(MenuItem, { value: "low", children: trans.__('Low') }), _jsx(MenuItem, { value: "medium", children: trans.__('Medium') }), _jsx(MenuItem, { value: "high", children: trans.__('High') })] })] }), _jsx(FormControlLabel, { control: _jsx(Switch, { checked: webSearchSettings.externalWebAccess !==
305
+ false, onChange: e => updateCustomSetting('webSearch', 'externalWebAccess', e.target.checked) }), label: trans.__('Use External Web Access') })] })), webSearchImplementation === 'anthropic' && (_jsxs(_Fragment, { children: [_jsx(TextField, { fullWidth: true, label: trans.__('Web Search Max Uses'), type: "number", value: webSearchSettings.maxUses ?? '', onChange: e => updateCustomSetting('webSearch', 'maxUses', e.target.value
306
+ ? Number(e.target.value)
307
+ : undefined), slotProps: { htmlInput: { min: 1 } } }), renderDomainList('webSearch.blockedDomains', trans.__('Blocked Domains'), trans.__('spam.example.com'), webSearchSettings.blockedDomains)] }))] }))] })), supportsWebFetch && (_jsxs(_Fragment, { children: [_jsx(FormControlLabel, { control: _jsx(Switch, { checked: webFetchSettings.enabled === true, onChange: e => updateCustomSetting('webFetch', 'enabled', e.target.checked) }), label: trans.__('Enable Web Fetch') }), webFetchSettings.enabled === true && (_jsxs(Box, { sx: {
308
+ pl: 2,
309
+ borderLeft: 2,
310
+ borderColor: 'divider',
311
+ display: 'flex',
312
+ flexDirection: 'column',
313
+ gap: 1.5
314
+ }, children: [_jsx(TextField, { fullWidth: true, label: trans.__('Web Fetch Max Uses'), type: "number", value: webFetchSettings.maxUses ?? '', onChange: e => updateCustomSetting('webFetch', 'maxUses', e.target.value
315
+ ? Number(e.target.value)
316
+ : undefined), slotProps: { htmlInput: { min: 1 } } }), _jsx(TextField, { fullWidth: true, label: trans.__('Web Fetch Max Content Tokens'), type: "number", value: webFetchSettings.maxContentTokens ?? '', onChange: e => updateCustomSetting('webFetch', 'maxContentTokens', e.target.value
317
+ ? Number(e.target.value)
318
+ : undefined), slotProps: { htmlInput: { min: 1 } } }), renderDomainList('webFetch.allowedDomains', trans.__('Allowed Domains'), trans.__('docs.example.com'), webFetchSettings.allowedDomains), renderDomainList('webFetch.blockedDomains', trans.__('Blocked Domains'), trans.__('spam.example.com'), webFetchSettings.blockedDomains), _jsx(FormControlLabel, { control: _jsx(Switch, { checked: webFetchSettings.citationsEnabled === true, onChange: e => updateCustomSetting('webFetch', 'citationsEnabled', e.target.checked) }), label: trans.__('Enable Citations') })] }))] }))] }))] }) })] })] }) }), _jsxs(DialogActions, { children: [_jsx(Button, { onClick: onClose, children: trans.__('Cancel') }), _jsx(Button, { onClick: handleSave, variant: "contained", disabled: !isValid, children: mode === 'add' ? trans.__('Add Provider') : trans.__('Save Changes') })] })] }));
384
319
  };