1use anyhow::Result;
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::path::PathBuf;
9use uuid::Uuid;
10
11use crate::{DebugConfig, InteractiveDebugger};
12
13#[derive(Debug)]
15pub struct IDEPlugin {
16 pub plugin_id: Uuid,
17 pub name: String,
18 pub version: String,
19 pub supported_ides: Vec<SupportedIDE>,
20 pub capabilities: IDECapabilities,
21 pub debugger: Option<InteractiveDebugger>,
22 pub config: DebugConfig,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub enum SupportedIDE {
28 VSCode,
29 IntelliJ,
30 Vim,
31 Emacs,
32 Sublime,
33 Atom,
34 Jupyter,
35 JupyterLab,
36 Custom(String),
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct IDECapabilities {
42 pub syntax_highlighting: bool,
43 pub code_completion: bool,
44 pub inline_debugging: bool,
45 pub tensor_visualization: bool,
46 pub real_time_metrics: bool,
47 pub breakpoint_management: bool,
48 pub call_stack_navigation: bool,
49 pub variable_inspection: bool,
50 pub performance_profiling: bool,
51 pub error_annotations: bool,
52 pub jupyter_widgets: bool,
53 pub interactive_plots: bool,
54 pub notebook_integration: bool,
55 pub kernel_communication: bool,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60pub enum IDEMessage {
61 StartDebugSession {
63 session_id: Uuid,
64 },
65 StopDebugSession {
66 session_id: Uuid,
67 },
68
69 SetBreakpoint {
71 file: PathBuf,
72 line: u32,
73 condition: Option<String>,
74 },
75 RemoveBreakpoint {
76 file: PathBuf,
77 line: u32,
78 },
79 ToggleBreakpoint {
80 file: PathBuf,
81 line: u32,
82 },
83
84 StepInto,
86 StepOver,
87 StepOut,
88 Continue,
89 Pause,
90
91 InspectVariable {
93 variable_name: String,
94 },
95 EvaluateExpression {
96 expression: String,
97 },
98
99 ShowTensorVisualization {
101 tensor_name: String,
102 },
103 ShowGradientFlow {
104 layer_name: String,
105 },
106 ShowLossLandscape,
107 ShowPerformanceMetrics,
108
109 GotoDefinition {
111 symbol: String,
112 },
113 FindReferences {
114 symbol: String,
115 },
116 ShowCallStack,
117
118 ShowError {
120 message: String,
121 file: Option<PathBuf>,
122 line: Option<u32>,
123 },
124 ShowWarning {
125 message: String,
126 file: Option<PathBuf>,
127 line: Option<u32>,
128 },
129
130 UpdateStatus {
132 status: String,
133 },
134 UpdateProgress {
135 progress: f64,
136 message: String,
137 },
138
139 CreateWidget {
141 widget_type: String,
142 widget_id: String,
143 options: HashMap<String, String>,
144 },
145 UpdateWidget {
146 widget_id: String,
147 data: HashMap<String, String>,
148 },
149 RemoveWidget {
150 widget_id: String,
151 },
152 ExecuteCell {
153 cell_content: String,
154 },
155 InsertCell {
156 content: String,
157 cell_type: String,
158 },
159 ShowNotebook {
160 notebook_content: String,
161 },
162 KernelRestart,
163 KernelInterrupt,
164 DisplayData {
165 data: HashMap<String, String>,
166 metadata: HashMap<String, String>,
167 },
168 StreamOutput {
169 stream_type: String,
170 text: String,
171 },
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
176pub enum IDEResponse {
177 SessionStarted {
179 session_id: Uuid,
180 },
181 SessionStopped {
182 session_id: Uuid,
183 },
184 SessionError {
185 error: String,
186 },
187
188 BreakpointSet {
190 file: PathBuf,
191 line: u32,
192 },
193 BreakpointRemoved {
194 file: PathBuf,
195 line: u32,
196 },
197 BreakpointHit {
198 file: PathBuf,
199 line: u32,
200 },
201
202 ExecutionPaused {
204 location: DebugLocation,
205 },
206 ExecutionResumed,
207 ExecutionStepped {
208 location: DebugLocation,
209 },
210
211 VariableValue {
213 name: String,
214 value: String,
215 type_name: String,
216 },
217 ExpressionResult {
218 expression: String,
219 result: String,
220 },
221
222 VisualizationData {
224 data_type: String,
225 data: Vec<u8>,
226 },
227 VisualizationPath {
228 path: PathBuf,
229 },
230
231 DefinitionLocation {
233 file: PathBuf,
234 line: u32,
235 column: u32,
236 },
237 ReferenceLocations {
238 locations: Vec<SourceLocation>,
239 },
240 CallStackData {
241 frames: Vec<CallStackFrame>,
242 },
243
244 Success {
246 message: String,
247 },
248 Error {
249 error: String,
250 },
251 Warning {
252 warning: String,
253 },
254
255 StatusUpdate {
257 status: String,
258 },
259 ProgressUpdate {
260 progress: f64,
261 message: String,
262 },
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
267pub struct DebugLocation {
268 pub file: PathBuf,
269 pub line: u32,
270 pub column: u32,
271 pub function: String,
272 pub module: String,
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct SourceLocation {
278 pub file: PathBuf,
279 pub line: u32,
280 pub column: u32,
281 pub context: String,
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
286pub struct CallStackFrame {
287 pub function: String,
288 pub file: PathBuf,
289 pub line: u32,
290 pub variables: HashMap<String, String>,
291}
292
293#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct IDEPluginConfig {
296 pub enable_syntax_highlighting: bool,
297 pub enable_code_completion: bool,
298 pub enable_inline_debugging: bool,
299 pub enable_tensor_visualization: bool,
300 pub enable_real_time_metrics: bool,
301 pub auto_open_debugger: bool,
302 pub visualization_format: String,
303 pub debug_port: u16,
304 pub max_variable_display_length: usize,
305 pub refresh_interval_ms: u64,
306 pub workspace_root: PathBuf,
307 pub log_level: String,
308}
309
310impl Default for IDEPluginConfig {
311 fn default() -> Self {
312 Self {
313 enable_syntax_highlighting: true,
314 enable_code_completion: true,
315 enable_inline_debugging: true,
316 enable_tensor_visualization: true,
317 enable_real_time_metrics: true,
318 auto_open_debugger: false,
319 visualization_format: "png".to_string(),
320 debug_port: 8899,
321 max_variable_display_length: 1000,
322 refresh_interval_ms: 1000,
323 workspace_root: PathBuf::from("."),
324 log_level: "info".to_string(),
325 }
326 }
327}
328
329impl IDEPlugin {
330 pub fn new(name: String, version: String, config: DebugConfig) -> Self {
332 Self {
333 plugin_id: Uuid::new_v4(),
334 name,
335 version,
336 supported_ides: vec![SupportedIDE::VSCode, SupportedIDE::IntelliJ],
337 capabilities: IDECapabilities {
338 syntax_highlighting: true,
339 code_completion: true,
340 inline_debugging: true,
341 tensor_visualization: true,
342 real_time_metrics: true,
343 breakpoint_management: true,
344 call_stack_navigation: true,
345 variable_inspection: true,
346 performance_profiling: true,
347 error_annotations: true,
348 jupyter_widgets: true,
349 interactive_plots: true,
350 notebook_integration: true,
351 kernel_communication: true,
352 },
353 debugger: None,
354 config,
355 }
356 }
357
358 pub async fn initialize(&mut self, debugger: InteractiveDebugger) -> Result<()> {
360 self.debugger = Some(debugger);
361 tracing::info!("IDE plugin '{}' initialized", self.name);
362 Ok(())
363 }
364
365 pub async fn handle_message(&mut self, message: IDEMessage) -> Result<IDEResponse> {
367 match message {
368 IDEMessage::StartDebugSession { session_id } => {
369 if let Some(ref mut debugger) = self.debugger {
370 debugger.start().await?;
371 Ok(IDEResponse::SessionStarted { session_id })
372 } else {
373 Ok(IDEResponse::SessionError {
374 error: "Debugger not initialized".to_string(),
375 })
376 }
377 },
378
379 IDEMessage::StopDebugSession { session_id } => {
380 if let Some(ref mut debugger) = self.debugger {
381 debugger.reset().await?;
382 Ok(IDEResponse::SessionStopped { session_id })
383 } else {
384 Ok(IDEResponse::SessionError {
385 error: "Debugger not initialized".to_string(),
386 })
387 }
388 },
389
390 IDEMessage::SetBreakpoint {
391 file,
392 line,
393 condition,
394 } => {
395 if let Some(ref debugger) = self.debugger {
396 let location = crate::interactive_debugger::DebugLocation {
397 module: file.file_stem().unwrap_or_default().to_string_lossy().to_string(),
398 function: "unknown".to_string(),
399 line: Some(line),
400 instruction: None,
401 context: Some(file.to_string_lossy().to_string()),
402 };
403
404 debugger
405 .process_command(
406 crate::interactive_debugger::DebuggerCommand::SetBreakpoint(
407 location, condition,
408 ),
409 )
410 .await?;
411
412 Ok(IDEResponse::BreakpointSet { file, line })
413 } else {
414 Ok(IDEResponse::Error {
415 error: "Debugger not initialized".to_string(),
416 })
417 }
418 },
419
420 IDEMessage::RemoveBreakpoint { file, line } => {
421 Ok(IDEResponse::BreakpointRemoved { file, line })
424 },
425
426 IDEMessage::StepInto => {
427 if let Some(ref debugger) = self.debugger {
428 let _response = debugger
429 .process_command(crate::interactive_debugger::DebuggerCommand::Step(
430 crate::interactive_debugger::StepMode::StepInto,
431 ))
432 .await?;
433
434 Ok(IDEResponse::ExecutionStepped {
435 location: DebugLocation {
436 file: PathBuf::from("unknown"),
437 line: 0,
438 column: 0,
439 function: "unknown".to_string(),
440 module: "unknown".to_string(),
441 },
442 })
443 } else {
444 Ok(IDEResponse::Error {
445 error: "Debugger not initialized".to_string(),
446 })
447 }
448 },
449
450 IDEMessage::StepOver => {
451 if let Some(ref debugger) = self.debugger {
452 debugger
453 .process_command(crate::interactive_debugger::DebuggerCommand::Step(
454 crate::interactive_debugger::StepMode::StepOver,
455 ))
456 .await?;
457
458 Ok(IDEResponse::ExecutionStepped {
459 location: DebugLocation {
460 file: PathBuf::from("unknown"),
461 line: 0,
462 column: 0,
463 function: "unknown".to_string(),
464 module: "unknown".to_string(),
465 },
466 })
467 } else {
468 Ok(IDEResponse::Error {
469 error: "Debugger not initialized".to_string(),
470 })
471 }
472 },
473
474 IDEMessage::Continue => {
475 if let Some(ref debugger) = self.debugger {
476 debugger
477 .process_command(crate::interactive_debugger::DebuggerCommand::Resume)
478 .await?;
479
480 Ok(IDEResponse::ExecutionResumed)
481 } else {
482 Ok(IDEResponse::Error {
483 error: "Debugger not initialized".to_string(),
484 })
485 }
486 },
487
488 IDEMessage::Pause => {
489 if let Some(ref debugger) = self.debugger {
490 debugger
491 .process_command(crate::interactive_debugger::DebuggerCommand::Pause)
492 .await?;
493
494 Ok(IDEResponse::ExecutionPaused {
495 location: DebugLocation {
496 file: PathBuf::from("unknown"),
497 line: 0,
498 column: 0,
499 function: "unknown".to_string(),
500 module: "unknown".to_string(),
501 },
502 })
503 } else {
504 Ok(IDEResponse::Error {
505 error: "Debugger not initialized".to_string(),
506 })
507 }
508 },
509
510 IDEMessage::InspectVariable { variable_name } => {
511 if let Some(ref debugger) = self.debugger {
512 let response = debugger
513 .process_command(
514 crate::interactive_debugger::DebuggerCommand::InspectVariable(
515 variable_name.clone(),
516 ),
517 )
518 .await?;
519
520 match response {
521 crate::interactive_debugger::DebuggerResponse::VariableInspected(var) => {
522 Ok(IDEResponse::VariableValue {
523 name: var.name,
524 value: var.value,
525 type_name: var.type_name,
526 })
527 },
528 _ => Ok(IDEResponse::Error {
529 error: format!("Variable '{}' not found", variable_name),
530 }),
531 }
532 } else {
533 Ok(IDEResponse::Error {
534 error: "Debugger not initialized".to_string(),
535 })
536 }
537 },
538
539 IDEMessage::EvaluateExpression { expression } => {
540 if let Some(ref debugger) = self.debugger {
541 let response = debugger
542 .process_command(
543 crate::interactive_debugger::DebuggerCommand::EvaluateExpression(
544 expression.clone(),
545 ),
546 )
547 .await?;
548
549 match response {
550 crate::interactive_debugger::DebuggerResponse::ExpressionEvaluated(
551 result,
552 ) => Ok(IDEResponse::ExpressionResult { expression, result }),
553 _ => Ok(IDEResponse::Error {
554 error: "Expression evaluation failed".to_string(),
555 }),
556 }
557 } else {
558 Ok(IDEResponse::Error {
559 error: "Debugger not initialized".to_string(),
560 })
561 }
562 },
563
564 IDEMessage::ShowCallStack => {
565 if let Some(ref debugger) = self.debugger {
566 let response = debugger
567 .process_command(
568 crate::interactive_debugger::DebuggerCommand::ShowCallStack,
569 )
570 .await?;
571
572 match response {
573 crate::interactive_debugger::DebuggerResponse::CallStackShown(frames) => {
574 let call_stack_frames: Vec<CallStackFrame> = frames
575 .into_iter()
576 .map(|frame| CallStackFrame {
577 function: frame.location.function,
578 file: PathBuf::from(frame.location.context.unwrap_or_default()),
579 line: frame.location.line.unwrap_or(0),
580 variables: frame
581 .locals
582 .into_iter()
583 .map(|(k, v)| (k, v.value))
584 .collect(),
585 })
586 .collect();
587
588 Ok(IDEResponse::CallStackData {
589 frames: call_stack_frames,
590 })
591 },
592 _ => Ok(IDEResponse::Error {
593 error: "Failed to get call stack".to_string(),
594 }),
595 }
596 } else {
597 Ok(IDEResponse::Error {
598 error: "Debugger not initialized".to_string(),
599 })
600 }
601 },
602
603 IDEMessage::ShowTensorVisualization { tensor_name } => {
604 Ok(IDEResponse::Success {
606 message: format!("Tensor visualization for '{}' requested", tensor_name),
607 })
608 },
609
610 IDEMessage::ShowGradientFlow { layer_name } => Ok(IDEResponse::Success {
611 message: format!("Gradient flow visualization for '{}' requested", layer_name),
612 }),
613
614 IDEMessage::ShowLossLandscape => Ok(IDEResponse::Success {
615 message: "Loss landscape visualization requested".to_string(),
616 }),
617
618 IDEMessage::ShowPerformanceMetrics => Ok(IDEResponse::Success {
619 message: "Performance metrics visualization requested".to_string(),
620 }),
621
622 IDEMessage::GotoDefinition { symbol: _ } => {
623 Ok(IDEResponse::DefinitionLocation {
625 file: PathBuf::from("src/lib.rs"),
626 line: 1,
627 column: 1,
628 })
629 },
630
631 IDEMessage::FindReferences { symbol } => {
632 Ok(IDEResponse::ReferenceLocations {
634 locations: vec![SourceLocation {
635 file: PathBuf::from("src/lib.rs"),
636 line: 1,
637 column: 1,
638 context: format!("Reference to {}", symbol),
639 }],
640 })
641 },
642
643 IDEMessage::ShowError {
644 message,
645 file,
646 line,
647 } => {
648 tracing::error!("IDE Error: {} at {:?}:{:?}", message, file, line);
649 Ok(IDEResponse::Success {
650 message: "Error displayed".to_string(),
651 })
652 },
653
654 IDEMessage::ShowWarning {
655 message,
656 file,
657 line,
658 } => {
659 tracing::warn!("IDE Warning: {} at {:?}:{:?}", message, file, line);
660 Ok(IDEResponse::Success {
661 message: "Warning displayed".to_string(),
662 })
663 },
664
665 IDEMessage::UpdateStatus { status } => Ok(IDEResponse::StatusUpdate { status }),
666
667 IDEMessage::UpdateProgress { progress, message } => {
668 Ok(IDEResponse::ProgressUpdate { progress, message })
669 },
670
671 _ => Ok(IDEResponse::Error {
672 error: "Unsupported message type".to_string(),
673 }),
674 }
675 }
676
677 pub fn generate_manifest(&self, ide: &SupportedIDE) -> Result<String> {
679 match ide {
680 SupportedIDE::VSCode => self.generate_vscode_manifest(),
681 SupportedIDE::IntelliJ => self.generate_intellij_manifest(),
682 SupportedIDE::Vim => self.generate_vim_manifest(),
683 SupportedIDE::Emacs => self.generate_emacs_manifest(),
684 _ => Ok("Generic plugin manifest".to_string()),
685 }
686 }
687
688 fn generate_vscode_manifest(&self) -> Result<String> {
689 let manifest = serde_json::json!({
690 "name": "trustformers-debug",
691 "displayName": "TrustformeRS Debug",
692 "description": "Advanced debugging tools for TrustformeRS models",
693 "version": self.version,
694 "engines": {
695 "vscode": "^1.60.0"
696 },
697 "categories": ["Debuggers", "Machine Learning"],
698 "main": "./out/extension.js",
699 "contributes": {
700 "debuggers": [{
701 "type": "trustformers",
702 "label": "TrustformeRS Debug",
703 "program": "./out/debugAdapter.js",
704 "runtime": "node",
705 "configurationAttributes": {
706 "launch": {
707 "required": ["program"],
708 "properties": {
709 "program": {
710 "type": "string",
711 "description": "Path to TrustformeRS program"
712 },
713 "args": {
714 "type": "array",
715 "description": "Command line arguments"
716 },
717 "cwd": {
718 "type": "string",
719 "description": "Working directory"
720 }
721 }
722 }
723 }
724 }],
725 "commands": [{
726 "command": "trustformers.showTensorVisualization",
727 "title": "Show Tensor Visualization",
728 "category": "TrustformeRS"
729 }, {
730 "command": "trustformers.showGradientFlow",
731 "title": "Show Gradient Flow",
732 "category": "TrustformeRS"
733 }, {
734 "command": "trustformers.showLossLandscape",
735 "title": "Show Loss Landscape",
736 "category": "TrustformeRS"
737 }]
738 },
739 "scripts": {
740 "vscode:prepublish": "npm run compile",
741 "compile": "tsc -p ./",
742 "watch": "tsc -watch -p ./"
743 }
744 });
745
746 Ok(serde_json::to_string_pretty(&manifest)?)
747 }
748
749 fn generate_intellij_manifest(&self) -> Result<String> {
750 let manifest = format!(
751 r#"<?xml version="1.0" encoding="UTF-8"?>
752<idea-plugin>
753 <id>com.trustformers.debug</id>
754 <name>TrustformeRS Debug</name>
755 <version>{}</version>
756 <vendor>TrustformeRS Team</vendor>
757
758 <description><![CDATA[
759 Advanced debugging tools for TrustformeRS models including:
760 - Interactive debugging
761 - Tensor visualization
762 - Gradient flow analysis
763 - Loss landscape visualization
764 ]]></description>
765
766 <depends>com.intellij.modules.platform</depends>
767 <depends>com.intellij.modules.lang</depends>
768
769 <extensions defaultExtensionNs="com.intellij">
770 <debugger.positionManagerFactory implementation="com.trustformers.debug.TrustformersPositionManagerFactory"/>
771 <xdebugger.breakpointType implementation="com.trustformers.debug.TrustformersLineBreakpointType"/>
772 <programRunner implementation="com.trustformers.debug.TrustformersDebugRunner"/>
773 <configurationType implementation="com.trustformers.debug.TrustformersConfigurationType"/>
774 </extensions>
775
776 <actions>
777 <action id="TrustformeRS.ShowTensorVisualization" class="com.trustformers.debug.actions.ShowTensorVisualizationAction" text="Show Tensor Visualization"/>
778 <action id="TrustformeRS.ShowGradientFlow" class="com.trustformers.debug.actions.ShowGradientFlowAction" text="Show Gradient Flow"/>
779 <action id="TrustformeRS.ShowLossLandscape" class="com.trustformers.debug.actions.ShowLossLandscapeAction" text="Show Loss Landscape"/>
780 </actions>
781</idea-plugin>"#,
782 self.version
783 );
784
785 Ok(manifest)
786 }
787
788 fn generate_vim_manifest(&self) -> Result<String> {
789 let manifest = format!(
790 r#"" TrustformeRS Debug Plugin for Vim
791" Version: {}
792" Description: Advanced debugging tools for TrustformeRS models
793
794if exists('g:loaded_trustformers_debug')
795 finish
796endif
797let g:loaded_trustformers_debug = 1
798
799" Plugin configuration
800let g:trustformers_debug_port = get(g:, 'trustformers_debug_port', 8899)
801let g:trustformers_debug_auto_open = get(g:, 'trustformers_debug_auto_open', 0)
802let g:trustformers_debug_visualization_format = get(g:, 'trustformers_debug_visualization_format', 'png')
803
804" Commands
805command! TrustformersStartDebug call trustformers#debug#start()
806command! TrustformersStopDebug call trustformers#debug#stop()
807command! TrustformersStepInto call trustformers#debug#step_into()
808command! TrustformersStepOver call trustformers#debug#step_over()
809command! TrustformersShowTensorVisualization call trustformers#debug#show_tensor_visualization()
810command! TrustformersShowGradientFlow call trustformers#debug#show_gradient_flow()
811command! TrustformersShowLossLandscape call trustformers#debug#show_loss_landscape()
812
813" Key mappings
814nnoremap <leader>tds :TrustformersStartDebug<CR>
815nnoremap <leader>tdt :TrustformersStopDebug<CR>
816nnoremap <leader>tdi :TrustformersStepInto<CR>
817nnoremap <leader>tdo :TrustformersStepOver<CR>
818nnoremap <leader>tdv :TrustformersShowTensorVisualization<CR>
819nnoremap <leader>tdg :TrustformersShowGradientFlow<CR>
820nnoremap <leader>tdl :TrustformersShowLossLandscape<CR>
821
822" Autocommands
823augroup TrustformersDebug
824 autocmd!
825 autocmd FileType rust call trustformers#debug#setup_buffer()
826augroup END"#,
827 self.version
828 );
829
830 Ok(manifest)
831 }
832
833 fn generate_emacs_manifest(&self) -> Result<String> {
834 let manifest = format!(
835 r#";;; trustformers-debug.el --- Advanced debugging tools for TrustformeRS models -*- lexical-binding: t; -*-
836
837;; Copyright (C) 2025-2026 COOLJAPAN OU (Team KitaSan)
838
839;; Author: COOLJAPAN OU (Team KitaSan)
840;; Version: {}
841;; Package-Requires: ((emacs "26.1"))
842;; Keywords: debugging, machine-learning, rust
843;; URL: https://github.com/cool-japan/trustformers
844
845;;; Commentary:
846
847;; This package provides advanced debugging tools for TrustformeRS models including:
848;; - Interactive debugging
849;; - Tensor visualization
850;; - Gradient flow analysis
851;; - Loss landscape visualization
852
853;;; Code:
854
855(require 'json)
856(require 'url)
857
858(defgroup trustformers-debug nil
859 "Advanced debugging tools for TrustformeRS models."
860 :group 'debugging
861 :prefix "trustformers-debug-")
862
863(defcustom trustformers-debug-port 8899
864 "Port for TrustformeRS debug server."
865 :type 'integer
866 :group 'trustformers-debug)
867
868(defcustom trustformers-debug-auto-open nil
869 "Whether to automatically open debug session."
870 :type 'boolean
871 :group 'trustformers-debug)
872
873(defvar trustformers-debug-mode-map
874 (let ((map (make-sparse-keymap)))
875 (define-key map (kbd "C-c C-d s") #'trustformers-debug-start)
876 (define-key map (kbd "C-c C-d t") #'trustformers-debug-stop)
877 (define-key map (kbd "C-c C-d i") #'trustformers-debug-step-into)
878 (define-key map (kbd "C-c C-d o") #'trustformers-debug-step-over)
879 (define-key map (kbd "C-c C-d v") #'trustformers-debug-show-tensor-visualization)
880 (define-key map (kbd "C-c C-d g") #'trustformers-debug-show-gradient-flow)
881 (define-key map (kbd "C-c C-d l") #'trustformers-debug-show-loss-landscape)
882 map)
883 "Keymap for TrustformeRS debug mode.")
884
885(define-minor-mode trustformers-debug-mode
886 "Minor mode for TrustformeRS debugging."
887 :lighter " TF-Debug"
888 :keymap trustformers-debug-mode-map)
889
890(defun trustformers-debug-start ()
891 "Start TrustformeRS debug session."
892 (interactive)
893 (message "Starting TrustformeRS debug session..."))
894
895(defun trustformers-debug-stop ()
896 "Stop TrustformeRS debug session."
897 (interactive)
898 (message "Stopping TrustformeRS debug session..."))
899
900(defun trustformers-debug-step-into ()
901 "Step into current function."
902 (interactive)
903 (message "Stepping into..."))
904
905(defun trustformers-debug-step-over ()
906 "Step over current line."
907 (interactive)
908 (message "Stepping over..."))
909
910(defun trustformers-debug-show-tensor-visualization ()
911 "Show tensor visualization."
912 (interactive)
913 (message "Showing tensor visualization..."))
914
915(defun trustformers-debug-show-gradient-flow ()
916 "Show gradient flow analysis."
917 (interactive)
918 (message "Showing gradient flow analysis..."))
919
920(defun trustformers-debug-show-loss-landscape ()
921 "Show loss landscape visualization."
922 (interactive)
923 (message "Showing loss landscape visualization..."))
924
925(provide 'trustformers-debug)
926;;; trustformers-debug.el ends here"#,
927 self.version
928 );
929
930 Ok(manifest)
931 }
932
933 pub fn get_supported_ides(&self) -> &[SupportedIDE] {
935 &self.supported_ides
936 }
937
938 pub fn get_capabilities(&self) -> &IDECapabilities {
940 &self.capabilities
941 }
942
943 pub fn is_initialized(&self) -> bool {
945 self.debugger.is_some()
946 }
947}
948
949#[derive(Debug)]
951pub struct IDEPluginManager {
952 plugins: HashMap<Uuid, IDEPlugin>,
953 active_sessions: HashMap<Uuid, Uuid>, }
955
956impl IDEPluginManager {
957 pub fn new() -> Self {
959 Self {
960 plugins: HashMap::new(),
961 active_sessions: HashMap::new(),
962 }
963 }
964
965 pub fn register_plugin(&mut self, plugin: IDEPlugin) -> Uuid {
967 let plugin_id = plugin.plugin_id;
968 self.plugins.insert(plugin_id, plugin);
969 plugin_id
970 }
971
972 pub fn get_plugin(&self, plugin_id: &Uuid) -> Option<&IDEPlugin> {
974 self.plugins.get(plugin_id)
975 }
976
977 pub fn get_plugin_mut(&mut self, plugin_id: &Uuid) -> Option<&mut IDEPlugin> {
979 self.plugins.get_mut(plugin_id)
980 }
981
982 pub fn start_session(&mut self, plugin_id: Uuid) -> Uuid {
984 let session_id = Uuid::new_v4();
985 self.active_sessions.insert(session_id, plugin_id);
986 session_id
987 }
988
989 pub fn stop_session(&mut self, session_id: &Uuid) -> Option<Uuid> {
991 self.active_sessions.remove(session_id)
992 }
993
994 pub fn get_all_plugins(&self) -> Vec<&IDEPlugin> {
996 self.plugins.values().collect()
997 }
998
999 pub fn get_active_sessions(&self) -> Vec<Uuid> {
1001 self.active_sessions.keys().cloned().collect()
1002 }
1003}
1004
1005impl Default for IDEPluginManager {
1006 fn default() -> Self {
1007 Self::new()
1008 }
1009}
1010
1011#[derive(Debug, Clone, Serialize, Deserialize)]
1013pub enum JupyterWidgetType {
1014 PlotWidget,
1016 TensorWidget,
1018 MetricsDashboard,
1020 GradientFlowWidget,
1022 ArchitectureWidget,
1024 ProfilerWidget,
1026 MemoryWidget,
1028 DebugConsole,
1030 ProgressBar,
1032 Custom(String),
1034}
1035
1036#[derive(Debug, Clone, Serialize, Deserialize)]
1038pub struct JupyterWidgetConfig {
1039 pub widget_id: String,
1040 pub widget_type: JupyterWidgetType,
1041 pub title: String,
1042 pub width: Option<u32>,
1043 pub height: Option<u32>,
1044 pub resizable: bool,
1045 pub auto_update: bool,
1046 pub update_interval: Option<u32>, pub options: HashMap<String, String>,
1048}
1049
1050#[derive(Debug, Clone, Serialize, Deserialize)]
1052pub struct JupyterWidgetData {
1053 pub plot_data: Option<crate::visualization::PlotData>,
1054 pub plot_3d_data: Option<crate::visualization::Plot3DData>,
1055 pub text_data: Option<String>,
1056 pub html_data: Option<String>,
1057 pub json_data: Option<String>,
1058 pub binary_data: Option<Vec<u8>>,
1059 pub metadata: HashMap<String, String>,
1060}
1061
1062#[derive(Debug)]
1064pub struct JupyterWidgetManager {
1065 widgets: HashMap<String, JupyterWidgetConfig>,
1066 kernel_connection: Option<String>,
1067 comm_targets: HashMap<String, String>,
1068}
1069
1070impl JupyterWidgetManager {
1071 pub fn new() -> Self {
1073 Self {
1074 widgets: HashMap::new(),
1075 kernel_connection: None,
1076 comm_targets: HashMap::new(),
1077 }
1078 }
1079
1080 pub fn connect_to_kernel(&mut self, connection_info: String) -> Result<()> {
1082 self.kernel_connection = Some(connection_info);
1083
1084 self.register_comm_target("trustformers_plot_widget".to_string());
1086 self.register_comm_target("trustformers_tensor_widget".to_string());
1087 self.register_comm_target("trustformers_metrics_widget".to_string());
1088 self.register_comm_target("trustformers_gradient_widget".to_string());
1089 self.register_comm_target("trustformers_debug_console".to_string());
1090
1091 Ok(())
1092 }
1093
1094 fn register_comm_target(&mut self, target_name: String) {
1096 let comm_id = Uuid::new_v4().to_string();
1097 self.comm_targets.insert(target_name, comm_id);
1098 }
1099
1100 pub fn create_widget(&mut self, config: JupyterWidgetConfig) -> Result<String> {
1102 let widget_id = config.widget_id.clone();
1103
1104 let widget_content = self.generate_widget_content(&config)?;
1106
1107 self.widgets.insert(widget_id.clone(), config);
1109
1110 self.send_widget_creation_message(&widget_id, &widget_content)?;
1112
1113 Ok(widget_id)
1114 }
1115
1116 pub fn update_widget(&mut self, widget_id: &str, data: JupyterWidgetData) -> Result<()> {
1118 let widget = self
1119 .widgets
1120 .get(widget_id)
1121 .ok_or_else(|| anyhow::anyhow!("Widget with id '{}' not found", widget_id))?;
1122
1123 let update_message = self.generate_update_message(widget, &data)?;
1125
1126 self.send_widget_update_message(widget_id, &update_message)?;
1128
1129 Ok(())
1130 }
1131
1132 pub fn remove_widget(&mut self, widget_id: &str) -> Result<()> {
1134 if self.widgets.remove(widget_id).is_some() {
1135 self.send_widget_removal_message(widget_id)?;
1136 Ok(())
1137 } else {
1138 Err(anyhow::anyhow!("Widget with id '{}' not found", widget_id))
1139 }
1140 }
1141
1142 pub fn create_plot_widget(
1144 &mut self,
1145 title: &str,
1146 plot_data: &crate::visualization::PlotData,
1147 ) -> Result<String> {
1148 let widget_id = format!("plot_{}", Uuid::new_v4().to_string().replace("-", ""));
1149
1150 let config = JupyterWidgetConfig {
1151 widget_id: widget_id.clone(),
1152 widget_type: JupyterWidgetType::PlotWidget,
1153 title: title.to_string(),
1154 width: Some(800),
1155 height: Some(600),
1156 resizable: true,
1157 auto_update: false,
1158 update_interval: None,
1159 options: HashMap::new(),
1160 };
1161
1162 self.create_widget(config)?;
1163
1164 let data = JupyterWidgetData {
1165 plot_data: Some(plot_data.clone()),
1166 plot_3d_data: None,
1167 text_data: None,
1168 html_data: None,
1169 json_data: None,
1170 binary_data: None,
1171 metadata: HashMap::new(),
1172 };
1173
1174 self.update_widget(&widget_id, data)?;
1175
1176 Ok(widget_id)
1177 }
1178
1179 pub fn create_metrics_dashboard(&mut self, title: &str) -> Result<String> {
1181 let widget_id = format!("metrics_{}", Uuid::new_v4().to_string().replace("-", ""));
1182
1183 let config = JupyterWidgetConfig {
1184 widget_id: widget_id.clone(),
1185 widget_type: JupyterWidgetType::MetricsDashboard,
1186 title: title.to_string(),
1187 width: Some(1000),
1188 height: Some(400),
1189 resizable: true,
1190 auto_update: true,
1191 update_interval: Some(1000), options: HashMap::new(),
1193 };
1194
1195 self.create_widget(config)?;
1196
1197 Ok(widget_id)
1198 }
1199
1200 pub fn create_gradient_flow_widget(&mut self, title: &str) -> Result<String> {
1202 let widget_id = format!("gradient_{}", Uuid::new_v4().to_string().replace("-", ""));
1203
1204 let config = JupyterWidgetConfig {
1205 widget_id: widget_id.clone(),
1206 widget_type: JupyterWidgetType::GradientFlowWidget,
1207 title: title.to_string(),
1208 width: Some(800),
1209 height: Some(500),
1210 resizable: true,
1211 auto_update: true,
1212 update_interval: Some(500), options: HashMap::new(),
1214 };
1215
1216 self.create_widget(config)?;
1217
1218 Ok(widget_id)
1219 }
1220
1221 pub fn create_debug_console(&mut self, title: &str) -> Result<String> {
1223 let widget_id = format!("console_{}", Uuid::new_v4().to_string().replace("-", ""));
1224
1225 let config = JupyterWidgetConfig {
1226 widget_id: widget_id.clone(),
1227 widget_type: JupyterWidgetType::DebugConsole,
1228 title: title.to_string(),
1229 width: Some(600),
1230 height: Some(300),
1231 resizable: true,
1232 auto_update: false,
1233 update_interval: None,
1234 options: HashMap::new(),
1235 };
1236
1237 self.create_widget(config)?;
1238
1239 Ok(widget_id)
1240 }
1241
1242 pub fn create_debug_dashboard(&mut self) -> Result<Vec<String>> {
1244 let mut widget_ids = Vec::new();
1245
1246 widget_ids.push(self.create_metrics_dashboard("Training Metrics")?);
1248 widget_ids.push(self.create_gradient_flow_widget("Gradient Flow")?);
1249 widget_ids.push(self.create_debug_console("Debug Console")?);
1250
1251 Ok(widget_ids)
1252 }
1253
1254 fn generate_widget_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1256 match &config.widget_type {
1257 JupyterWidgetType::PlotWidget => self.generate_plot_widget_content(config),
1258 JupyterWidgetType::TensorWidget => self.generate_tensor_widget_content(config),
1259 JupyterWidgetType::MetricsDashboard => self.generate_metrics_dashboard_content(config),
1260 JupyterWidgetType::GradientFlowWidget => self.generate_gradient_widget_content(config),
1261 JupyterWidgetType::ArchitectureWidget => {
1262 self.generate_architecture_widget_content(config)
1263 },
1264 JupyterWidgetType::ProfilerWidget => self.generate_profiler_widget_content(config),
1265 JupyterWidgetType::MemoryWidget => self.generate_memory_widget_content(config),
1266 JupyterWidgetType::DebugConsole => self.generate_debug_console_content(config),
1267 JupyterWidgetType::ProgressBar => self.generate_progress_bar_content(config),
1268 JupyterWidgetType::Custom(widget_type) => {
1269 self.generate_custom_widget_content(config, widget_type)
1270 },
1271 }
1272 }
1273
1274 fn generate_plot_widget_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1276 let content = format!(
1277 r#"
1278<div id="{widget_id}" style="width: {width}px; height: {height}px; border: 1px solid #ccc; border-radius: 4px;">
1279 <div id="{widget_id}_plot" style="width: 100%; height: 100%;"></div>
1280</div>
1281
1282<script>
1283requirejs(['https://cdn.plot.ly/plotly-2.26.0.min.js'], function(Plotly) {{
1284 window.trustformers_widgets = window.trustformers_widgets || {{}};
1285 window.trustformers_widgets['{widget_id}'] = {{
1286 element: document.getElementById('{widget_id}_plot'),
1287 update: function(data) {{
1288 if (data.plot_data) {{
1289 const trace = {{
1290 x: data.plot_data.x_values,
1291 y: data.plot_data.y_values,
1292 type: 'scatter',
1293 mode: 'lines+markers',
1294 name: 'Data',
1295 line: {{ color: '#007bff', width: 2 }},
1296 marker: {{ size: 6 }}
1297 }};
1298
1299 const layout = {{
1300 title: data.plot_data.title,
1301 xaxis: {{ title: data.plot_data.x_label }},
1302 yaxis: {{ title: data.plot_data.y_label }},
1303 margin: {{ t: 50, l: 60, r: 30, b: 60 }},
1304 showlegend: false
1305 }};
1306
1307 Plotly.newPlot(this.element, [trace], layout, {{ responsive: true }});
1308 }}
1309 }}
1310 }};
1311}});
1312</script>
1313"#,
1314 widget_id = config.widget_id,
1315 width = config.width.unwrap_or(800),
1316 height = config.height.unwrap_or(600)
1317 );
1318
1319 Ok(content)
1320 }
1321
1322 fn generate_tensor_widget_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1324 let content = format!(
1325 r#"
1326<div id="{widget_id}" class="trustformers-tensor-widget" style="width: {width}px; height: {height}px; padding: 10px; border: 1px solid #ddd; border-radius: 4px; background: #f9f9f9;">
1327 <h3>{title}</h3>
1328 <div id="{widget_id}_content" style="height: calc(100% - 40px); overflow-y: auto;">
1329 <div id="{widget_id}_stats"></div>
1330 <div id="{widget_id}_visualization"></div>
1331 </div>
1332</div>
1333
1334<script>
1335window.trustformers_widgets = window.trustformers_widgets || {{}};
1336window.trustformers_widgets['{widget_id}'] = {{
1337 update: function(data) {{
1338 const statsDiv = document.getElementById('{widget_id}_stats');
1339 const vizDiv = document.getElementById('{widget_id}_visualization');
1340
1341 if (data.text_data) {{
1342 statsDiv.innerHTML = '<pre>' + data.text_data + '</pre>';
1343 }}
1344
1345 if (data.html_data) {{
1346 vizDiv.innerHTML = data.html_data;
1347 }}
1348 }}
1349}};
1350</script>
1351"#,
1352 widget_id = config.widget_id,
1353 title = config.title,
1354 width = config.width.unwrap_or(600),
1355 height = config.height.unwrap_or(400)
1356 );
1357
1358 Ok(content)
1359 }
1360
1361 fn generate_metrics_dashboard_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1363 let content = format!(
1364 r#"
1365<div id="{widget_id}" class="trustformers-metrics-dashboard" style="width: {width}px; height: {height}px; border: 1px solid #ccc; border-radius: 4px; background: white;">
1366 <div style="background: #f8f9fa; padding: 10px; border-bottom: 1px solid #dee2e6;">
1367 <h4 style="margin: 0;">{title}</h4>
1368 </div>
1369 <div id="{widget_id}_metrics" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; padding: 10px; height: calc(100% - 60px); overflow-y: auto;">
1370 <!-- Metrics will be populated here -->
1371 </div>
1372</div>
1373
1374<script>
1375window.trustformers_widgets = window.trustformers_widgets || {{}};
1376window.trustformers_widgets['{widget_id}'] = {{
1377 update: function(data) {{
1378 const metricsDiv = document.getElementById('{widget_id}_metrics');
1379
1380 if (data.json_data) {{
1381 const metrics = JSON.parse(data.json_data);
1382 let html = '';
1383
1384 for (const [key, value] of Object.entries(metrics)) {{
1385 html += `
1386 <div style="background: #f8f9fa; padding: 10px; border-radius: 4px; text-align: center;">
1387 <div style="font-size: 14px; color: #6c757d; margin-bottom: 4px;">${{key}}</div>
1388 <div style="font-size: 20px; font-weight: bold; color: #495057;">${{value}}</div>
1389 </div>
1390 `;
1391 }}
1392
1393 metricsDiv.innerHTML = html;
1394 }}
1395 }}
1396}};
1397
1398// Auto-update if enabled
1399{auto_update_script}
1400</script>
1401"#,
1402 widget_id = config.widget_id,
1403 title = config.title,
1404 width = config.width.unwrap_or(1000),
1405 height = config.height.unwrap_or(400),
1406 auto_update_script = if config.auto_update {
1407 format!(
1408 r#"
1409setInterval(function() {{
1410 // Request updated metrics from kernel
1411 if (window.trustformers_kernel_comm) {{
1412 window.trustformers_kernel_comm.send({{
1413 widget_id: '{widget_id}',
1414 action: 'request_update'
1415 }});
1416 }}
1417}}, {});
1418"#,
1419 config.update_interval.unwrap_or(1000),
1420 widget_id = config.widget_id
1421 )
1422 } else {
1423 "".to_string()
1424 }
1425 );
1426
1427 Ok(content)
1428 }
1429
1430 fn generate_gradient_widget_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1432 let content = format!(
1434 r#"
1435<div id="{widget_id}" class="trustformers-gradient-widget" style="width: {width}px; height: {height}px; border: 1px solid #ccc; border-radius: 4px;">
1436 <div style="background: #f8f9fa; padding: 10px; border-bottom: 1px solid #dee2e6;">
1437 <h4 style="margin: 0;">{title}</h4>
1438 </div>
1439 <div id="{widget_id}_gradient_plot" style="width: 100%; height: calc(100% - 60px);"></div>
1440</div>
1441
1442<script>
1443requirejs(['https://cdn.plot.ly/plotly-2.26.0.min.js'], function(Plotly) {{
1444 window.trustformers_widgets = window.trustformers_widgets || {{}};
1445 window.trustformers_widgets['{widget_id}'] = {{
1446 element: document.getElementById('{widget_id}_gradient_plot'),
1447 update: function(data) {{
1448 if (data.plot_data) {{
1449 const trace = {{
1450 x: data.plot_data.x_values,
1451 y: data.plot_data.y_values,
1452 type: 'bar',
1453 marker: {{ color: '#dc3545' }},
1454 name: 'Gradient Norm'
1455 }};
1456
1457 const layout = {{
1458 title: 'Gradient Flow by Layer',
1459 xaxis: {{ title: 'Layer' }},
1460 yaxis: {{ title: 'Gradient Norm', type: 'log' }},
1461 margin: {{ t: 50, l: 60, r: 30, b: 60 }}
1462 }};
1463
1464 Plotly.newPlot(this.element, [trace], layout, {{ responsive: true }});
1465 }}
1466 }}
1467 }};
1468}});
1469</script>
1470"#,
1471 widget_id = config.widget_id,
1472 title = config.title,
1473 width = config.width.unwrap_or(800),
1474 height = config.height.unwrap_or(500)
1475 );
1476
1477 Ok(content)
1478 }
1479
1480 fn generate_architecture_widget_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1482 Ok(format!(
1484 "<div id='{}'>Architecture Widget - {}</div>",
1485 config.widget_id, config.title
1486 ))
1487 }
1488
1489 fn generate_profiler_widget_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1491 Ok(format!(
1493 "<div id='{}'>Profiler Widget - {}</div>",
1494 config.widget_id, config.title
1495 ))
1496 }
1497
1498 fn generate_memory_widget_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1500 Ok(format!(
1502 "<div id='{}'>Memory Widget - {}</div>",
1503 config.widget_id, config.title
1504 ))
1505 }
1506
1507 fn generate_debug_console_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1509 let content = format!(
1510 r#"
1511<div id="{widget_id}" class="trustformers-debug-console" style="width: {width}px; height: {height}px; border: 1px solid #ccc; border-radius: 4px; background: #1e1e1e; color: #d4d4d4; font-family: 'Courier New', monospace;">
1512 <div style="background: #2d2d30; padding: 8px; border-bottom: 1px solid #3e3e42; color: #cccccc; font-size: 12px;">
1513 {title}
1514 </div>
1515 <div id="{widget_id}_output" style="height: calc(100% - 90px); overflow-y: auto; padding: 10px; font-size: 12px; line-height: 1.4;">
1516 <!-- Console output will appear here -->
1517 </div>
1518 <div style="border-top: 1px solid #3e3e42; padding: 5px;">
1519 <input id="{widget_id}_input" type="text" placeholder="Enter debug command..."
1520 style="width: 100%; background: #3c3c3c; border: 1px solid #5a5a5a; color: #d4d4d4; padding: 5px; border-radius: 2px; font-family: inherit; font-size: 12px;">
1521 </div>
1522</div>
1523
1524<script>
1525window.trustformers_widgets = window.trustformers_widgets || {{}};
1526window.trustformers_widgets['{widget_id}'] = {{
1527 outputDiv: document.getElementById('{widget_id}_output'),
1528 inputEl: document.getElementById('{widget_id}_input'),
1529
1530 init: function() {{
1531 this.inputEl.addEventListener('keypress', (e) => {{
1532 if (e.key === 'Enter') {{
1533 const command = this.inputEl.value;
1534 this.addOutput('> ' + command, 'input');
1535 this.inputEl.value = '';
1536
1537 // Send command to kernel
1538 if (window.trustformers_kernel_comm) {{
1539 window.trustformers_kernel_comm.send({{
1540 widget_id: '{widget_id}',
1541 action: 'execute_command',
1542 command: command
1543 }});
1544 }}
1545 }}
1546 }});
1547 }},
1548
1549 addOutput: function(text, type = 'output') {{
1550 const div = document.createElement('div');
1551 div.style.marginBottom = '2px';
1552 div.style.color = type === 'input' ? '#569cd6' :
1553 type === 'error' ? '#f14c4c' : '#d4d4d4';
1554 div.textContent = text;
1555 this.outputDiv.appendChild(div);
1556 this.outputDiv.scrollTop = this.outputDiv.scrollHeight;
1557 }},
1558
1559 update: function(data) {{
1560 if (data.text_data) {{
1561 this.addOutput(data.text_data, data.metadata.type || 'output');
1562 }}
1563 }}
1564}};
1565
1566window.trustformers_widgets['{widget_id}'].init();
1567</script>
1568"#,
1569 widget_id = config.widget_id,
1570 title = config.title,
1571 width = config.width.unwrap_or(600),
1572 height = config.height.unwrap_or(300)
1573 );
1574
1575 Ok(content)
1576 }
1577
1578 fn generate_progress_bar_content(&self, config: &JupyterWidgetConfig) -> Result<String> {
1580 Ok(format!(
1582 "<div id='{}'>Progress Bar - {}</div>",
1583 config.widget_id, config.title
1584 ))
1585 }
1586
1587 fn generate_custom_widget_content(
1589 &self,
1590 config: &JupyterWidgetConfig,
1591 widget_type: &str,
1592 ) -> Result<String> {
1593 Ok(format!(
1595 "<div id='{}'>Custom Widget ({}) - {}</div>",
1596 config.widget_id, widget_type, config.title
1597 ))
1598 }
1599
1600 fn generate_update_message(
1602 &self,
1603 config: &JupyterWidgetConfig,
1604 data: &JupyterWidgetData,
1605 ) -> Result<String> {
1606 let message = serde_json::json!({
1607 "widget_id": config.widget_id,
1608 "data": {
1609 "plot_data": data.plot_data,
1610 "plot_3d_data": data.plot_3d_data,
1611 "text_data": data.text_data,
1612 "html_data": data.html_data,
1613 "json_data": data.json_data,
1614 "metadata": data.metadata
1615 }
1616 });
1617
1618 Ok(message.to_string())
1619 }
1620
1621 fn send_widget_creation_message(&self, widget_id: &str, content: &str) -> Result<()> {
1623 tracing::info!("Creating Jupyter widget: {}", widget_id);
1625 tracing::debug!("Widget content: {}", content);
1626 Ok(())
1627 }
1628
1629 fn send_widget_update_message(&self, widget_id: &str, message: &str) -> Result<()> {
1631 tracing::debug!("Updating Jupyter widget {}: {}", widget_id, message);
1633 Ok(())
1634 }
1635
1636 fn send_widget_removal_message(&self, widget_id: &str) -> Result<()> {
1638 tracing::info!("Removing Jupyter widget: {}", widget_id);
1640 Ok(())
1641 }
1642
1643 pub fn get_active_widgets(&self) -> Vec<&JupyterWidgetConfig> {
1645 self.widgets.values().collect()
1646 }
1647
1648 pub fn is_kernel_connected(&self) -> bool {
1650 self.kernel_connection.is_some()
1651 }
1652
1653 pub fn get_widget(&self, widget_id: &str) -> Option<&JupyterWidgetConfig> {
1655 self.widgets.get(widget_id)
1656 }
1657}
1658
1659impl Default for JupyterWidgetManager {
1660 fn default() -> Self {
1661 Self::new()
1662 }
1663}