or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

communication.mderror-handling.mdindex.mdlayout-style.mdnativeview.mdregistry.mdutilities.mdwidget-classes.mdwidget-manager.md
tile.json

communication.mddocs/

0

# Communication

1

2

The communication layer provides bidirectional messaging between Jupyter widgets in the frontend and their corresponding models in the kernel through comm channels and message handling.

3

4

## Capabilities

5

6

### IClassicComm Interface

7

8

Core interface for communication channels between frontend widgets and kernel models.

9

10

```typescript { .api }

11

/**

12

* Interface for Jupyter comm communication channels

13

*/

14

interface IClassicComm {

15

/**

16

* Unique identifier for the communication channel

17

*/

18

comm_id: string;

19

20

/**

21

* Target name identifying the comm type

22

*/

23

target_name: string;

24

25

/**

26

* Open a communication channel to the kernel

27

* @param data - Initial data to send

28

* @param callbacks - Message callback handlers

29

* @param metadata - Additional message metadata

30

* @param buffers - Binary data buffers

31

* @returns Message ID of the open message

32

*/

33

open(

34

data: JSONValue,

35

callbacks?: ICallbacks,

36

metadata?: JSONObject,

37

buffers?: ArrayBuffer[] | ArrayBufferView[]

38

): string;

39

40

/**

41

* Send a message through the communication channel

42

* @param data - Message data payload

43

* @param callbacks - Message callback handlers

44

* @param metadata - Additional message metadata

45

* @param buffers - Binary data buffers

46

* @returns Message ID of the sent message

47

*/

48

send(

49

data: JSONValue,

50

callbacks?: ICallbacks,

51

metadata?: JSONObject,

52

buffers?: ArrayBuffer[] | ArrayBufferView[]

53

): string;

54

55

/**

56

* Close the communication channel

57

* @param data - Optional closing data

58

* @param callbacks - Message callback handlers

59

* @param metadata - Additional message metadata

60

* @param buffers - Binary data buffers

61

* @returns Message ID of the close message

62

*/

63

close(

64

data?: JSONValue,

65

callbacks?: ICallbacks,

66

metadata?: JSONObject,

67

buffers?: ArrayBuffer[] | ArrayBufferView[]

68

): string;

69

70

/**

71

* Register a handler for incoming messages

72

* @param callback - Function to handle received messages

73

*/

74

on_msg(callback: (x: any) => void): void;

75

76

/**

77

* Register a handler for comm close events

78

* @param callback - Function to handle comm closure

79

*/

80

on_close(callback: (x: any) => void): void;

81

}

82

```

83

84

**Usage Examples:**

85

86

```typescript

87

// Setup message handling

88

comm.on_msg((msg) => {

89

console.log('Received message:', msg);

90

// Handle different message types

91

switch (msg.content.method) {

92

case 'update':

93

handleStateUpdate(msg.content.state);

94

break;

95

case 'custom':

96

handleCustomMessage(msg.content.data);

97

break;

98

}

99

});

100

101

// Setup close handling

102

comm.on_close((msg) => {

103

console.log('Comm closed:', msg);

104

cleanup();

105

});

106

107

// Send messages with callbacks

108

const msgId = comm.send(

109

{ method: 'request_data', params: { type: 'summary' } },

110

{

111

shell: {

112

reply: (msg) => console.log('Got reply:', msg)

113

},

114

iopub: {

115

status: (msg) => console.log('Status:', msg.content.execution_state)

116

}

117

}

118

);

119

```

120

121

### Message Callbacks

122

123

Configuration for handling different types of kernel messages during comm operations.

124

125

```typescript { .api }

126

/**

127

* Callback handlers for different message channels

128

*/

129

interface ICallbacks {

130

/**

131

* Handlers for shell messages (replies, errors)

132

*/

133

shell?: {

134

[key: string]: (msg: KernelMessage.IShellMessage) => void

135

};

136

137

/**

138

* Handlers for IOPub messages (status, output, errors)

139

*/

140

iopub?: {

141

[key: string]: (msg: KernelMessage.IIOPubMessage) => void

142

};

143

144

/**

145

* Handler for stdin messages (input requests)

146

*/

147

input?: (msg: KernelMessage.IStdinMessage) => void;

148

}

149

```

150

151

**Usage Examples:**

152

153

```typescript

154

// Comprehensive callback setup

155

const callbacks: ICallbacks = {

156

shell: {

157

reply: (msg) => {

158

// Handle successful replies

159

console.log('Operation completed:', msg.content);

160

},

161

error: (msg) => {

162

// Handle errors

163

console.error('Operation failed:', msg.content);

164

}

165

},

166

iopub: {

167

status: (msg) => {

168

// Track kernel execution state

169

const state = msg.content.execution_state;

170

if (state === 'busy') {

171

showSpinner();

172

} else if (state === 'idle') {

173

hideSpinner();

174

}

175

},

176

execute_result: (msg) => {

177

// Handle execution results

178

displayResult(msg.content.data);

179

},

180

stream: (msg) => {

181

// Handle stdout/stderr output

182

appendOutput(msg.content.text);

183

},

184

error: (msg) => {

185

// Handle execution errors

186

displayError(msg.content.ename, msg.content.evalue, msg.content.traceback);

187

}

188

},

189

input: (msg) => {

190

// Handle input requests from kernel

191

const prompt = msg.content.prompt;

192

const response = await getUserInput(prompt);

193

// Send response back to kernel

194

}

195

};

196

197

// Use callbacks with comm operations

198

comm.send(data, callbacks);

199

```

200

201

## Services Shim Layer

202

203

Compatibility layer that provides the classic comm API while using modern @jupyterlab/services underneath.

204

205

### CommManager

206

207

Manager class for creating and registering communication channels.

208

209

```typescript { .api }

210

/**

211

* Manager for communication channels, provides compatibility with @jupyterlab/services

212

*/

213

class CommManager {

214

/**

215

* Initialize comm manager with kernel connection

216

* @param jsServicesKernel - @jupyterlab/services kernel connection

217

*/

218

constructor(jsServicesKernel: Kernel.IKernelConnection);

219

220

/**

221

* Setup or update kernel connection

222

* @param jsServicesKernel - @jupyterlab/services kernel connection

223

*/

224

init_kernel(jsServicesKernel: Kernel.IKernelConnection): void;

225

226

/**

227

* Create a new communication channel

228

* @param target_name - Comm target identifier

229

* @param data - Initial data to send

230

* @param callbacks - Message callbacks

231

* @param metadata - Message metadata

232

* @param comm_id - Specific comm ID to use

233

* @param buffers - Binary data buffers

234

* @returns Promise resolving to the created comm

235

*/

236

async new_comm(

237

target_name: string,

238

data: any,

239

callbacks: any,

240

metadata: any,

241

comm_id: string,

242

buffers?: ArrayBuffer[] | ArrayBufferView[]

243

): Promise<Comm>;

244

245

/**

246

* Register a handler for incoming comm creation requests

247

* @param target_name - Target name to handle

248

* @param f - Handler function receiving comm and message

249

*/

250

register_target(

251

target_name: string,

252

f: (comm: Comm, object: KernelMessage.IMessage) => void

253

): void;

254

255

/**

256

* Unregister a comm target handler

257

* @param target_name - Target name to unregister

258

* @param f - Handler function to remove

259

*/

260

unregister_target(

261

target_name: string,

262

f: (comm: Comm, object: KernelMessage.IMessage) => void

263

): void;

264

265

/**

266

* Register a comm instance with the manager

267

* @param comm - Comm instance to register

268

* @returns Comm ID

269

*/

270

register_comm(comm: Comm): string;

271

}

272

```

273

274

### Comm Implementation

275

276

Wrapper class that implements IClassicComm using @jupyterlab/services IComm.

277

278

```typescript { .api }

279

/**

280

* Comm implementation wrapping @jupyterlab/services IComm

281

*/

282

class Comm implements IClassicComm {

283

/**

284

* Create comm wrapper

285

* @param jsServicesComm - @jupyterlab/services IComm instance

286

*/

287

constructor(jsServicesComm: Kernel.IComm);

288

289

/**

290

* Get the comm identifier

291

*/

292

get comm_id(): string;

293

294

/**

295

* Get the target name

296

*/

297

get target_name(): string;

298

299

/**

300

* Open the comm channel

301

* @param data - Opening data

302

* @param callbacks - Message callbacks

303

* @param metadata - Message metadata

304

* @param buffers - Binary buffers

305

* @returns Message ID

306

*/

307

open(

308

data: JSONValue,

309

callbacks?: ICallbacks,

310

metadata?: JSONObject,

311

buffers?: ArrayBuffer[] | ArrayBufferView[]

312

): string;

313

314

/**

315

* Send message through comm

316

* @param data - Message data

317

* @param callbacks - Message callbacks

318

* @param metadata - Message metadata

319

* @param buffers - Binary buffers

320

* @returns Message ID

321

*/

322

send(

323

data: JSONValue,

324

callbacks?: ICallbacks,

325

metadata?: JSONObject,

326

buffers?: ArrayBuffer[] | ArrayBufferView[]

327

): string;

328

329

/**

330

* Close the comm channel

331

* @param data - Closing data

332

* @param callbacks - Message callbacks

333

* @param metadata - Message metadata

334

* @param buffers - Binary buffers

335

* @returns Message ID

336

*/

337

close(

338

data?: JSONValue,

339

callbacks?: ICallbacks,

340

metadata?: JSONObject,

341

buffers?: ArrayBuffer[] | ArrayBufferView[]

342

): string;

343

344

/**

345

* Register message handler

346

* @param callback - Message handler function

347

*/

348

on_msg(callback: (x: any) => void): void;

349

350

/**

351

* Register close handler

352

* @param callback - Close handler function

353

*/

354

on_close(callback: (x: any) => void): void;

355

}

356

```

357

358

**Usage Examples:**

359

360

```typescript

361

// Initialize comm manager

362

const kernel = await kernelManager.startNew();

363

const commManager = new CommManager(kernel);

364

365

// Register comm target

366

commManager.register_target('my_widget', (comm, msg) => {

367

console.log('New widget comm created:', comm.comm_id);

368

369

// Setup handlers for this comm

370

comm.on_msg((msg) => {

371

handleWidgetMessage(comm, msg);

372

});

373

374

comm.on_close((msg) => {

375

cleanupWidget(comm.comm_id);

376

});

377

});

378

379

// Create new comm

380

const comm = await commManager.new_comm(

381

'my_widget',

382

{ widget_type: 'slider', initial_value: 50 },

383

callbacks,

384

{},

385

'slider-widget-1'

386

);

387

```

388

389

## Message Patterns

390

391

### Widget State Synchronization

392

393

```typescript

394

// Handle state updates from kernel

395

comm.on_msg((msg) => {

396

if (msg.content.method === 'update') {

397

const state = msg.content.state;

398

const bufferPaths = msg.content.buffer_paths || [];

399

const buffers = msg.buffers || [];

400

401

// Reconstruct state with binary data

402

put_buffers(state, bufferPaths, buffers);

403

404

// Apply state to model

405

model.set_state(state);

406

}

407

});

408

409

// Send state changes to kernel

410

const sendStateUpdate = (changes: any) => {

411

// Remove binary buffers for transmission

412

const { state, buffer_paths, buffers } = remove_buffers(changes);

413

414

comm.send({

415

method: 'update',

416

state: state,

417

buffer_paths: buffer_paths

418

}, callbacks, {}, buffers);

419

};

420

```

421

422

### Custom Message Handling

423

424

```typescript

425

// Send custom messages

426

const sendCustomMessage = (action: string, data: any) => {

427

comm.send({

428

method: 'custom',

429

content: {

430

action: action,

431

data: data,

432

timestamp: Date.now()

433

}

434

});

435

};

436

437

// Handle custom messages

438

comm.on_msg((msg) => {

439

if (msg.content.method === 'custom') {

440

const { action, data } = msg.content.content;

441

442

switch (action) {

443

case 'highlight':

444

highlightWidget(data.color);

445

break;

446

case 'reset':

447

resetWidget();

448

break;

449

case 'export':

450

exportData(data.format);

451

break;

452

}

453

}

454

});

455

```

456

457

### Error Handling and Recovery

458

459

```typescript

460

// Robust message sending with error handling

461

const sendMessageWithRetry = async (data: any, maxRetries = 3) => {

462

let attempt = 0;

463

464

while (attempt < maxRetries) {

465

try {

466

const msgId = comm.send(data, {

467

shell: {

468

reply: (msg) => {

469

console.log('Message sent successfully:', msgId);

470

},

471

error: (msg) => {

472

console.error('Message failed:', msg);

473

throw new Error(`Message failed: ${msg.content.ename}`);

474

}

475

}

476

});

477

return msgId;

478

} catch (error) {

479

attempt++;

480

if (attempt >= maxRetries) {

481

throw error;

482

}

483

await new Promise(resolve => setTimeout(resolve, 1000 * attempt));

484

}

485

}

486

};

487

488

// Connection state management

489

let connectionState = 'connected';

490

491

comm.on_close(() => {

492

connectionState = 'disconnected';

493

// Attempt reconnection

494

setTimeout(attemptReconnection, 5000);

495

});

496

497

const attemptReconnection = async () => {

498

try {

499

// Create new comm with same ID

500

const newComm = await commManager.new_comm(

501

comm.target_name,

502

{ reconnect: true },

503

callbacks,

504

{},

505

comm.comm_id

506

);

507

connectionState = 'connected';

508

console.log('Reconnected successfully');

509

} catch (error) {

510

console.error('Reconnection failed:', error);

511

setTimeout(attemptReconnection, 10000);

512

}

513

};

514

```

515

516

## Buffer Handling

517

518

Working with binary data in widget communication:

519

520

```typescript

521

// Send data with binary buffers

522

const sendBinaryData = (imageData: Uint8Array, metadata: any) => {

523

const data = {

524

metadata: metadata,

525

image: imageData // This will be extracted as a buffer

526

};

527

528

// remove_buffers extracts binary data

529

const { state, buffer_paths, buffers } = remove_buffers(data);

530

531

comm.send({

532

method: 'update',

533

state: state,

534

buffer_paths: buffer_paths

535

}, callbacks, {}, buffers);

536

};

537

538

// Receive data with binary buffers

539

comm.on_msg((msg) => {

540

if (msg.content.buffer_paths && msg.buffers) {

541

const state = msg.content.state;

542

const bufferPaths = msg.content.buffer_paths;

543

const buffers = msg.buffers;

544

545

// Reconstruct object with binary data

546

put_buffers(state, bufferPaths, buffers);

547

548

// Now state.image is a DataView containing the binary data

549

const imageData = new Uint8Array(state.image.buffer);

550

displayImage(imageData);

551

}

552

});

553

```