@jupyterlite/ai 0.9.1 → 0.11.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/README.md +5 -214
- package/lib/agent.d.ts +58 -66
- package/lib/agent.js +291 -310
- package/lib/approval-buttons.d.ts +19 -82
- package/lib/approval-buttons.js +36 -289
- package/lib/chat-model-registry.d.ts +6 -0
- package/lib/chat-model-registry.js +4 -1
- package/lib/chat-model.d.ts +26 -54
- package/lib/chat-model.js +277 -303
- package/lib/components/clear-button.d.ts +6 -1
- package/lib/components/clear-button.js +10 -6
- package/lib/components/completion-status.d.ts +5 -0
- package/lib/components/completion-status.js +5 -4
- package/lib/components/model-select.d.ts +6 -1
- package/lib/components/model-select.js +13 -16
- package/lib/components/stop-button.d.ts +6 -1
- package/lib/components/stop-button.js +12 -8
- package/lib/components/token-usage-display.d.ts +5 -0
- package/lib/components/token-usage-display.js +2 -2
- package/lib/components/tool-select.d.ts +6 -1
- package/lib/components/tool-select.js +10 -9
- package/lib/index.d.ts +1 -0
- package/lib/index.js +61 -81
- package/lib/models/settings-model.d.ts +1 -1
- package/lib/models/settings-model.js +40 -26
- package/lib/providers/built-in-providers.js +38 -19
- package/lib/providers/models.d.ts +3 -3
- package/lib/providers/provider-registry.d.ts +3 -4
- package/lib/providers/provider-registry.js +1 -4
- package/lib/tokens.d.ts +5 -6
- package/lib/tools/commands.d.ts +2 -1
- package/lib/tools/commands.js +36 -49
- package/lib/widgets/ai-settings.d.ts +6 -0
- package/lib/widgets/ai-settings.js +72 -71
- package/lib/widgets/main-area-chat.d.ts +2 -0
- package/lib/widgets/main-area-chat.js +5 -2
- package/lib/widgets/provider-config-dialog.d.ts +2 -0
- package/lib/widgets/provider-config-dialog.js +34 -34
- package/package.json +13 -13
- package/schema/settings-model.json +3 -2
- package/src/agent.ts +360 -372
- package/src/approval-buttons.ts +43 -389
- package/src/chat-model-registry.ts +9 -1
- package/src/chat-model.ts +399 -370
- package/src/completion/completion-provider.ts +2 -3
- package/src/components/clear-button.tsx +18 -6
- package/src/components/completion-status.tsx +18 -4
- package/src/components/model-select.tsx +25 -16
- package/src/components/stop-button.tsx +22 -9
- package/src/components/token-usage-display.tsx +14 -2
- package/src/components/tool-select.tsx +27 -9
- package/src/index.ts +78 -134
- package/src/models/settings-model.ts +41 -27
- package/src/providers/built-in-providers.ts +38 -19
- package/src/providers/models.ts +3 -3
- package/src/providers/provider-registry.ts +4 -8
- package/src/tokens.ts +5 -6
- package/src/tools/commands.ts +40 -53
- package/src/widgets/ai-settings.tsx +153 -84
- package/src/widgets/main-area-chat.ts +8 -2
- package/src/widgets/provider-config-dialog.tsx +54 -41
- package/style/base.css +24 -73
- package/lib/mcp/browser.d.ts +0 -68
- package/lib/mcp/browser.js +0 -138
- package/lib/tools/file.d.ts +0 -36
- package/lib/tools/file.js +0 -351
- package/lib/tools/notebook.d.ts +0 -40
- package/lib/tools/notebook.js +0 -779
- package/src/mcp/browser.ts +0 -220
- package/src/tools/file.ts +0 -438
- package/src/tools/notebook.ts +0 -986
|
@@ -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'
|
|
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:
|
|
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,
|
|
97
|
-
React.createElement(Select, { value: provider, label:
|
|
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:
|
|
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:
|
|
104
|
-
React.createElement(InputLabel, null,
|
|
105
|
-
React.createElement(Select, { value: model, label:
|
|
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:
|
|
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:
|
|
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" },
|
|
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" },
|
|
160
|
-
React.createElement(TextField, { fullWidth: true, label:
|
|
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
|
-
|
|
162
|
+
maxOutputTokens: e.target.value
|
|
163
163
|
? Number(e.target.value)
|
|
164
164
|
: undefined
|
|
165
|
-
}), placeholder:
|
|
166
|
-
React.createElement(TextField, { fullWidth: true, label:
|
|
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:
|
|
172
|
-
React.createElement(Typography, { variant: "body2", color: "text.secondary", sx: { mt: 2, mb: 1 } },
|
|
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:
|
|
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:
|
|
180
|
+
}) }), label: trans.__('Use filter text') })))))),
|
|
181
181
|
React.createElement(DialogActions, null,
|
|
182
|
-
React.createElement(Button, { onClick: onClose },
|
|
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.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "AI code completions and chat for JupyterLite",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -51,15 +51,18 @@
|
|
|
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/@/\\@/g' CHANGELOG.md > docs/_changelog_content.md && jupyter book build --html"
|
|
55
57
|
},
|
|
56
58
|
"dependencies": {
|
|
57
|
-
"@ai-sdk/anthropic": "^
|
|
58
|
-
"@ai-sdk/google": "^
|
|
59
|
-
"@ai-sdk/
|
|
60
|
-
"@ai-sdk/
|
|
61
|
-
"@ai-sdk/openai
|
|
62
|
-
"@
|
|
59
|
+
"@ai-sdk/anthropic": "^3.0.23",
|
|
60
|
+
"@ai-sdk/google": "^3.0.13",
|
|
61
|
+
"@ai-sdk/mcp": "^1.0.13",
|
|
62
|
+
"@ai-sdk/mistral": "^3.0.12",
|
|
63
|
+
"@ai-sdk/openai": "^3.0.18",
|
|
64
|
+
"@ai-sdk/openai-compatible": "^2.0.18",
|
|
65
|
+
"@jupyter/chat": "^0.19.0-alpha.3",
|
|
63
66
|
"@jupyterlab/application": "^4.0.0",
|
|
64
67
|
"@jupyterlab/apputils": "^4.5.6",
|
|
65
68
|
"@jupyterlab/cells": "^4.4.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
|
-
"
|
|
88
|
-
"@openai/agents-extensions": "^0.1.5",
|
|
89
|
-
"ai": "^5.0.60",
|
|
89
|
+
"ai": "^6.0.49",
|
|
90
90
|
"jupyter-secrets-manager": "^0.4.0",
|
|
91
|
-
"zod": "^3.
|
|
91
|
+
"zod": "^4.3.6"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@jupyterlab/builder": "^4.0.0",
|
|
@@ -155,14 +155,15 @@
|
|
|
155
155
|
"fileeditor:run-code",
|
|
156
156
|
"kernelmenu:run",
|
|
157
157
|
"kernelmenu:restart-and-run-all",
|
|
158
|
-
"runmenu:run-all"
|
|
158
|
+
"runmenu:run-all",
|
|
159
|
+
"jupyterlab-ai-commands:run-cell"
|
|
159
160
|
]
|
|
160
161
|
},
|
|
161
162
|
"systemPrompt": {
|
|
162
163
|
"title": "System Prompt",
|
|
163
164
|
"description": "Instructions that define how the AI should behave and respond",
|
|
164
165
|
"type": "string",
|
|
165
|
-
"default": "You are Jupyternaut, an AI coding assistant built specifically for the JupyterLab environment.\n\n## Your Core Mission\nYou're designed to be a capable partner for data science, research, and development work in Jupyter notebooks. You can help with everything from quick code snippets to complex multi-notebook projects.\n\n## Your Capabilities\n**📁 File & Project Management:**\n- Create, read, edit, and organize
|
|
166
|
+
"default": "You are Jupyternaut, an AI coding assistant built specifically for the JupyterLab environment.\n\n## Your Core Mission\nYou're designed to be a capable partner for data science, research, and development work in Jupyter notebooks. You can help with everything from quick code snippets to complex multi-notebook projects.\n\n## Your Capabilities\n**📁 File & Project Management:**\n- Create, read, edit, and organize files and notebooks in any language\n- Manage project structure and navigate file systems\n- Help with version control and project organization\n\n**📊 Notebook Operations:**\n- Create new notebooks and manage existing ones\n- Add, edit, delete, and run cells (both code and markdown)\n- Help with notebook structure and organization\n- Retrieve and analyze cell outputs and execution results\n\n**⚡ Kernel Management:**\n- Start new kernels with specified language or kernel name\n- Execute code directly in running kernels without creating cells\n- List running kernels and monitor their status\n- Manage kernel lifecycle (start, monitor, shutdown)\n\n**🧠 Coding & Development:**\n- Write, debug, and optimize code in any language supported by Jupyter kernels (Python, R, Julia, JavaScript, C++, and more)\n- Explain complex algorithms and data structures\n- Help with data analysis, visualization, and machine learning\n- Support for libraries and packages across different languages\n- Code reviews and best practices recommendations\n\n**💡 Adaptive Assistance:**\n- Understand context from the user's current work environment\n- Provide suggestions tailored to the user's specific use case\n- Help with both quick fixes and long-term project planning\n\n## How You Work\nYou interact with the user's JupyterLab environment primarily through the command system:\n- Use 'discover_commands' to find available JupyterLab commands\n- Use 'execute_command' to perform operations\n- For file and notebook operations, use commands from the jupyterlab-ai-commands extension (prefixed with 'jupyterlab-ai-commands:')\n- These commands provide comprehensive file and notebook manipulation: create, read, edit files/notebooks, manage cells, run code, etc.\n- You can make systematic changes across multiple files and perform complex multi-step operations\n\n## Code Execution Strategy\nWhen asked to run code or perform computations, choose the most appropriate approach:\n- **For quick computations or one-off code execution**: Use kernel commands to start a kernel and execute code directly, without creating notebook files. This is ideal for calculations, data lookups, or testing code snippets.\n- **For work that should be saved**: Create or use notebooks when the user needs a persistent record of their work, wants to iterate on code, or is building something they'll return to later.\n\nThis means if the user asks you to \"calculate the factorial of 100\" or \"check what library version is installed\", run that directly in a kernel rather than creating a new notebook file.\n\n## Your Approach\n- **Context-aware**: You understand the user is working in a data science/research environment\n- **Practical**: You focus on actionable solutions that work in the user's current setup\n- **Educational**: You explain your reasoning and teach best practices along the way\n- **Collaborative**: You are a pair programming partner, not just a code generator\n\n## Communication Style & Agent Behavior\n- **Conversational**: You maintain a friendly, natural conversation flow throughout the interaction\n- **Progress Updates**: You write brief progress messages between tool uses that appear directly in the conversation\n- **No Filler**: You avoid empty acknowledgments like \"Sounds good!\" or \"Okay, I will...\" - you get straight to work\n- **Purposeful Communication**: You start with what you're doing, use tools, then share what you found and what's next\n- **Active Narration**: You actively write progress updates like \"Looking at the current code structure...\" or \"Found the issue in the notebook...\" between tool calls\n- **Checkpoint Updates**: After several operations, you summarize what you've accomplished and what remains\n- **Natural Flow**: Your explanations and progress reports appear as normal conversation text, not just in tool blocks\n\n## IMPORTANT: Always write progress messages between tools that explain what you're doing and what you found. These should be conversational updates that help the user follow along with your work.\n\n## Technical Communication\n- Code is formatted in proper markdown blocks with syntax highlighting\n- Mathematical notation uses LaTeX formatting: \\\\(equations\\\\) and \\\\[display math\\\\]\n- You provide context for your actions and explain your reasoning as you work\n- When creating or modifying multiple files, you give brief summaries of changes\n- You keep users informed of progress while staying focused on the task\n\n## Multi-Step Task Handling\nWhen users request complex tasks, you use the command system to accomplish them:\n- For file and notebook operations, use discover_commands with query 'jupyterlab-ai-commands' to find the curated set of AI commands (~17 commands)\n- For other JupyterLab operations (terminal, launcher, UI), use specific keywords like 'terminal', 'launcher', etc.\n- IMPORTANT: Always use 'jupyterlab-ai-commands' as the query for file/notebook tasks - this returns a focused set instead of 100+ generic commands\n- For example, to create a notebook with cells:\n 1. discover_commands with query 'jupyterlab-ai-commands' to find available file/notebook commands\n 2. execute_command with 'jupyterlab-ai-commands:create-notebook' and required arguments\n 3. execute_command with 'jupyterlab-ai-commands:add-cell' multiple times to add cells\n 4. execute_command with 'jupyterlab-ai-commands:set-cell-content' to add content to cells\n 5. execute_command with 'jupyterlab-ai-commands:run-cell' when appropriate\n\n## Kernel Preference for Notebooks and Consoles\nWhen creating notebooks or consoles for a specific programming language, use the 'kernelPreference' argument:\n- To specify by language: { \"kernelPreference\": { \"language\": \"python\" } } or { \"kernelPreference\": { \"language\": \"julia\" } }\n- To specify by kernel name: { \"kernelPreference\": { \"name\": \"python3\" } } or { \"kernelPreference\": { \"name\": \"julia-1.10\" } }\n- Example: execute_command with commandId=\"notebook:create-new\" and args={ \"kernelPreference\": { \"language\": \"python\" } }\n- Example: execute_command with commandId=\"console:create\" and args={ \"kernelPreference\": { \"name\": \"python3\" } }\n- Common kernel names: \"python3\" (Python), \"julia-1.10\" (Julia), \"ir\" (R), \"xpython\" (xeus-python)\n- If unsure of exact kernel name, prefer using \"language\" which will match any kernel supporting that language\n\nAlways think through multi-step tasks and use commands to fully complete the user's request rather than stopping after just one action.\n\nYou are ready to help users build something great!"
|
|
166
167
|
},
|
|
167
168
|
"completionSystemPrompt": {
|
|
168
169
|
"title": "Completion System Prompt",
|