-
Notifications
You must be signed in to change notification settings - Fork 11
Getting model from widget first than fallback to documentManager #237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Thanks @nakul-py for working in this. After a quick test, it works well on my side with cell but with a notebook I have something like Can you use the types of objects instead of |
|
@brichet I have used all the needed object types but still i get Here is the code private async _readFileAttachment(
attachment: IAttachment
): Promise<string | null> {
// Handle both 'file' and 'notebook' types since both have a 'value' path
if (attachment.type !== 'file' && attachment.type !== 'notebook') {
return null;
}
try {
// Try reading from an open widget first
const widget = this.input.documentManager?.findWidget(attachment.value);
if (widget && widget.context && widget.context.model) {
const model = widget.context.model as DocumentRegistry.IModel;
const sharedText = (model as any).sharedModel as
| ISharedText
| undefined;
if (sharedText && typeof sharedText.getSource === 'function') {
return sharedText.getSource();
}
const sharedNb = (model as any).sharedModel as
| ISharedNotebook
| undefined;
if (sharedNb && typeof sharedNb.getCell === 'function') {
const cells: nbformat.ICell[] = [];
for (let i = 0; i < sharedNb.cells.length; i++) {
const cell = sharedNb.getCell(i);
const cellJSON = cell.toJSON();
cells.push({
...cellJSON,
outputs: [],
execution_count: null
});
}
const nb: nbformat.INotebookContent = {
cells,
metadata: sharedNb.getMetadata(),
nbformat: 4,
nbformat_minor: 5
};
return JSON.stringify(nb);
}
}
// If not open, load from disk
const diskModel = await this.input.documentManager?.services.contents.get(
attachment.value
);
if (!diskModel?.content) {
return null;
}
if (diskModel.type === 'file') {
// Regular file content
return diskModel.content;
}
if (diskModel.type === 'notebook') {
const cleaned = {
...diskModel,
cells: diskModel.content.cells.map((cell: any) => ({
...cell,
outputs: [],
execution_count: null
}))
};
return JSON.stringify(cleaned);
}
return null;
} catch (error) {
console.warn(`Failed to read file ${attachment.value}:`, error);
return null;
}
} |
src/chat-model.ts
Outdated
| return null; | ||
| } | ||
| // Try reading from live notebook if open | ||
| const widget = this.input.documentManager?.findWidget(attachment.value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I know, the widget can only be a IDocumentWidget<Notebook, INotebookModel> | undefined.
Casting it would avoid typing the following sharedModel and cells as any.
Did you see use case where the widget is of another type ?
src/chat-model.ts
Outdated
| : JSON.stringify(source, null, 2); | ||
| } | ||
|
|
||
| if ((model as any).sharedModel?.getCells) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we reach this comparison ?
As in the comment above, the widget should only be a IDocumentWidget<Notebook, INotebookModel> | undefined, so the model should be INotebookModel, with sharedModel.getSource always defined (and the previous comparison always return the source).
brichet
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @nakul-py for updating the PR 👍
I have some nitpick comments
src/chat-model.ts
Outdated
| return null; | ||
| } | ||
| ) as IDocumentWidget<Notebook, INotebookModel> | undefined; | ||
| let cellData: nbformat.ICell[] | null = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let cellData: nbformat.ICell[] | null = null; | |
| let cellData: nbformat.ICell[]; |
src/chat-model.ts
Outdated
| if (!model || model.type !== 'notebook') { | ||
| return null; | ||
| } | ||
| cellData = model.content.cells; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| cellData = model.content.cells; | |
| cellData = model.content.cells ?? []; |
Related to above comment
src/chat-model.ts
Outdated
| const cell = model.content.cells.find( | ||
| (c: any) => c.id === cellInfo.id | ||
| ); | ||
| const cell = cellData!.find(c => c.id === cellInfo.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const cell = cellData!.find(c => c.id === cellInfo.id); | |
| const cell = cellData.find(c => c.id === cellInfo.id); |
Related to above comments
src/chat-model.ts
Outdated
| let cellData: nbformat.ICell[] | null = null; | ||
| let kernelLang = 'text'; | ||
|
|
||
| const ymodel = widget?.context?.model?.sharedModel as YNotebook; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const ymodel = widget?.context?.model?.sharedModel as YNotebook; | |
| const ymodel = widget?.context.model.sharedModel as YNotebook; |
src/chat-model.ts
Outdated
| nb.metadata?.language_info?.name || | ||
| nb.metadata?.kernelspec?.language || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| nb.metadata?.language_info?.name || | |
| nb.metadata?.kernelspec?.language || | |
| nb.metadata.language_info?.name || | |
| nb.metadata.kernelspec?.language || |
src/chat-model.ts
Outdated
| : JSON.stringify(source, null, 2); | ||
| } | ||
|
|
||
| if (typeof ymodel.toJSON === 'function') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we reach this comparison ?
The YNotebook always has a getSource() function defined, AFAIK https://github.com/jupyter-server/jupyter_ydoc/blob/fdbf658e072467f49048ddef513a5e569207f25b/javascript/src/ynotebook.ts#L408
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes you are correct Nicolas!. This comparison is unreachable as you say earlier YNotebook always implements getSource(), and getSource() internally calls toJSON().
|
@brichet Now everything looks fine. 👍 |
brichet
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @nakul-py, looks great!
First try to getting model from
widgetthan fallback todocumentManagerfor both files and notebook cells.file_widget.mp4
cell_widget.mp4
documentManager#234cc @jtpio @brichet