目标:
DeepAnalyze。src/index.ts:扩展入口,注册命令、向 Launcher 注入入口、构建并打开自定义主界面。src/deepanalyze/widget.tsx(或 src/deepanalyze/widget.ts):把 UI 组合逻辑从 index.ts 拆出来,便于维护。ILauncher(@jupyterlab/launcher)MainAreaWidget(@jupyterlab/apputils)NotebookPanel/NotebookActions(@jupyterlab/notebook)Terminal(@jupyterlab/terminal)app.serviceManager.contents(@jupyterlab/services),文件浏览器 IFileBrowserFactory(@jupyterlab/filebrowser)SplitPanel(@lumino/widgets)在 src/index.ts 的 plugin 里:
ILauncher、IFileBrowserFactory(至少这两个)。deepanalyze:open)。launcher.add({ command, category, rank }) 把命令放进 Launcher。建议的插件骨架(结构要点,按需增减依赖):
const plugin: JupyterFrontEndPlugin<void> = {
id: 'deepanalyze:plugin',
autoStart: true,
requires: [ILauncher, IFileBrowserFactory],
activate: (app, launcher, browserFactory) => {
const command = 'deepanalyze:open';
app.commands.addCommand(command, {
label: 'DeepAnalyze',
execute: () => openDeepAnalyze(app, browserFactory)
});
launcher.add({ command, category: 'Other', rank: 50 });
}
};
建议策略:每次进入模式时创建一个唯一目录,例如 DeepAnalyze-YYYYMMDD-HHMMSS/,并切到该目录。
关键调用(示意):
const { contents } = app.serviceManager;
const dir = await contents.newUntitled({ type: 'directory', path: '' });
await browserFactory.defaultBrowser.model.cd(dir.path);
思路:用 Lumino 的 SplitPanel 组合三个区域:
SplitPanel(水平):[ 中间Notebook | 右侧SplitPanel ]SplitPanel(垂直):[ 终端 | 右下Notebook ]关键点:
docManager.newUntitled 创建 .ipynb,再用 docManager.openOrReveal 打开为 NotebookPanel,这样自带 kernel/session 生命周期。app.serviceManager.terminals.startNew(),再用 Terminal widget 绑定。MainAreaWidget 并 app.shell.add(widget, 'main')。补充:终端依赖 Jupyter Server 允许 terminals(有些部署会禁用)。如果你发现终端不可用,优先检查服务器配置与权限;或临时用自定义“聊天面板”替代真实终端 widget。
JupyterFrontEndPlugin)、命令系统(app.commands)、Shell 区域(app.shell)。SplitPanel、BoxPanel、widget 生命周期(dispose())。NotebookPanel.content.model、cell/outputs 结构。@jupyterlab/services)。jlpm watch + jupyter lab(见仓库 README.md)。jlpm testui-tests/README.md