@trops/dash-core 0.1.49 → 0.1.51

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.
@@ -528,6 +528,8 @@ const LLM_ABORT_REQUEST$1 = "llm-abort-request";
528
528
  const LLM_LIST_CONNECTED_TOOLS$1 = "llm-list-connected-tools";
529
529
  const LLM_CHECK_CLI_AVAILABLE$1 = "llm-check-cli-available";
530
530
  const LLM_CLEAR_CLI_SESSION$1 = "llm-clear-cli-session";
531
+ const LLM_CLI_SESSION_STATUS$1 = "llm-cli-session-status";
532
+ const LLM_CLI_END_SESSION$1 = "llm-cli-end-session";
531
533
 
532
534
  // --- Main → Renderer (send) ---
533
535
  const LLM_STREAM_DELTA$3 = "llm-stream-delta";
@@ -547,6 +549,8 @@ var llmEvents$1 = {
547
549
  LLM_STREAM_TOOL_RESULT: LLM_STREAM_TOOL_RESULT$3,
548
550
  LLM_STREAM_COMPLETE: LLM_STREAM_COMPLETE$3,
549
551
  LLM_STREAM_ERROR: LLM_STREAM_ERROR$3,
552
+ LLM_CLI_SESSION_STATUS: LLM_CLI_SESSION_STATUS$1,
553
+ LLM_CLI_END_SESSION: LLM_CLI_END_SESSION$1,
550
554
  };
551
555
 
552
556
  /**
@@ -6704,6 +6708,52 @@ const cliController$2 = {
6704
6708
  }
6705
6709
  return { success: false };
6706
6710
  },
6711
+
6712
+ /**
6713
+ * getSessionStatus
6714
+ * Check if a CLI session exists and whether a process is active for a widget.
6715
+ *
6716
+ * @param {string} widgetUuid - the widget to check
6717
+ * @returns {{ hasSession: boolean, sessionId?: string, isProcessActive: boolean }}
6718
+ */
6719
+ getSessionStatus: (widgetUuid) => {
6720
+ const sessionId = widgetUuid ? sessions.get(widgetUuid) : null;
6721
+ // Check if any active process belongs to this widget
6722
+ let isProcessActive = false;
6723
+ for (const [, child] of activeProcesses) {
6724
+ if (!child.killed) {
6725
+ isProcessActive = true;
6726
+ break;
6727
+ }
6728
+ }
6729
+ return {
6730
+ hasSession: !!sessionId,
6731
+ sessionId: sessionId || undefined,
6732
+ isProcessActive,
6733
+ };
6734
+ },
6735
+
6736
+ /**
6737
+ * endSession
6738
+ * Kill any active CLI process AND clear the session for a widget.
6739
+ *
6740
+ * @param {string} widgetUuid - the widget whose session to end
6741
+ * @returns {{ success: boolean }}
6742
+ */
6743
+ endSession: (widgetUuid) => {
6744
+ // Kill any active processes for this widget
6745
+ for (const [reqId, child] of activeProcesses) {
6746
+ if (reqId.startsWith(widgetUuid)) {
6747
+ child.kill("SIGTERM");
6748
+ activeProcesses.delete(reqId);
6749
+ }
6750
+ }
6751
+ // Clear the session
6752
+ if (widgetUuid && sessions.has(widgetUuid)) {
6753
+ sessions.delete(widgetUuid);
6754
+ }
6755
+ return { success: true };
6756
+ },
6707
6757
  };
6708
6758
 
6709
6759
  var cliController_1 = cliController$2;
@@ -8289,6 +8339,8 @@ const {
8289
8339
  LLM_LIST_CONNECTED_TOOLS,
8290
8340
  LLM_CHECK_CLI_AVAILABLE,
8291
8341
  LLM_CLEAR_CLI_SESSION,
8342
+ LLM_CLI_SESSION_STATUS,
8343
+ LLM_CLI_END_SESSION,
8292
8344
  LLM_STREAM_DELTA,
8293
8345
  LLM_STREAM_TOOL_CALL,
8294
8346
  LLM_STREAM_TOOL_RESULT,
@@ -8296,6 +8348,17 @@ const {
8296
8348
  LLM_STREAM_ERROR,
8297
8349
  } = llmEvents$1;
8298
8350
 
8351
+ let _nextListenerId = 0;
8352
+ const _listenerMap = new Map();
8353
+
8354
+ function _addListener(channel, callback) {
8355
+ const id = String(++_nextListenerId);
8356
+ const wrapped = (_event, data) => callback(data);
8357
+ ipcRenderer$2.on(channel, wrapped);
8358
+ _listenerMap.set(id, { channel, wrapped });
8359
+ return id;
8360
+ }
8361
+
8299
8362
  const llmApi$2 = {
8300
8363
  /**
8301
8364
  * sendMessage
@@ -8344,53 +8407,73 @@ const llmApi$2 = {
8344
8407
  clearCliSession: (widgetUuid) =>
8345
8408
  ipcRenderer$2.invoke(LLM_CLEAR_CLI_SESSION, { widgetUuid }),
8346
8409
 
8347
- // --- Stream event listeners ---
8348
-
8349
8410
  /**
8350
- * onStreamDelta
8351
- * Listen for text chunks as they stream in.
8411
+ * getCliSessionStatus
8412
+ * Check if a CLI session is active for a widget.
8413
+ *
8414
+ * @param {string} widgetUuid - the widget to check
8415
+ * @returns {Promise<{ hasSession: boolean, sessionId?: string, isProcessActive: boolean }>}
8352
8416
  */
8353
- onStreamDelta: (callback) => {
8354
- ipcRenderer$2.on(LLM_STREAM_DELTA, (_event, data) => callback(data));
8355
- },
8417
+ getCliSessionStatus: (widgetUuid) =>
8418
+ ipcRenderer$2.invoke(LLM_CLI_SESSION_STATUS, { widgetUuid }),
8356
8419
 
8357
8420
  /**
8358
- * onStreamToolCall
8359
- * Listen for tool call notifications.
8421
+ * endCliSession
8422
+ * Kill any active CLI process AND clear the session for a widget.
8423
+ *
8424
+ * @param {string} widgetUuid - the widget whose session to end
8425
+ * @returns {Promise<{ success: boolean }>}
8360
8426
  */
8361
- onStreamToolCall: (callback) => {
8362
- ipcRenderer$2.on(LLM_STREAM_TOOL_CALL, (_event, data) => callback(data));
8363
- },
8427
+ endCliSession: (widgetUuid) =>
8428
+ ipcRenderer$2.invoke(LLM_CLI_END_SESSION, { widgetUuid }),
8364
8429
 
8365
- /**
8366
- * onStreamToolResult
8367
- * Listen for tool result notifications.
8368
- */
8369
- onStreamToolResult: (callback) => {
8370
- ipcRenderer$2.on(LLM_STREAM_TOOL_RESULT, (_event, data) => callback(data));
8371
- },
8430
+ // --- Stream event listeners ---
8431
+ // Each on* method returns an opaque string ID. Strings cross the
8432
+ // contextBridge safely (unlike function refs which get proxied).
8433
+ // Use removeStreamListener(id) to clean up.
8372
8434
 
8373
- /**
8374
- * onStreamComplete
8375
- * Listen for stream completion (final response).
8376
- */
8377
- onStreamComplete: (callback) => {
8378
- ipcRenderer$2.on(LLM_STREAM_COMPLETE, (_event, data) => callback(data));
8379
- },
8435
+ /** @returns {string} listener ID */
8436
+ onStreamDelta: (callback) => _addListener(LLM_STREAM_DELTA, callback),
8437
+
8438
+ /** @returns {string} listener ID */
8439
+ onStreamToolCall: (callback) => _addListener(LLM_STREAM_TOOL_CALL, callback),
8440
+
8441
+ /** @returns {string} listener ID */
8442
+ onStreamToolResult: (callback) =>
8443
+ _addListener(LLM_STREAM_TOOL_RESULT, callback),
8444
+
8445
+ /** @returns {string} listener ID */
8446
+ onStreamComplete: (callback) => _addListener(LLM_STREAM_COMPLETE, callback),
8447
+
8448
+ /** @returns {string} listener ID */
8449
+ onStreamError: (callback) => _addListener(LLM_STREAM_ERROR, callback),
8380
8450
 
8381
8451
  /**
8382
- * onStreamError
8383
- * Listen for stream errors.
8452
+ * removeStreamListener
8453
+ * Remove a specific stream listener by its opaque ID.
8454
+ *
8455
+ * @param {string} idOrChannel - listener ID (or legacy channel name when second arg is provided)
8456
+ * @param {string} [id] - listener ID when called with legacy (channel, id) signature
8384
8457
  */
8385
- onStreamError: (callback) => {
8386
- ipcRenderer$2.on(LLM_STREAM_ERROR, (_event, data) => callback(data));
8458
+ removeStreamListener: (idOrChannel, id) => {
8459
+ const listenerId = id !== undefined ? String(id) : String(idOrChannel);
8460
+ const entry = _listenerMap.get(listenerId);
8461
+ if (entry) {
8462
+ ipcRenderer$2.removeListener(entry.channel, entry.wrapped);
8463
+ _listenerMap.delete(listenerId);
8464
+ }
8387
8465
  },
8388
8466
 
8389
8467
  /**
8390
8468
  * removeAllStreamListeners
8391
- * Clean up all LLM stream listeners.
8469
+ * Clean up ALL LLM stream listeners (global).
8470
+ * Prefer removeStreamListener for scoped cleanup.
8392
8471
  */
8393
8472
  removeAllStreamListeners: () => {
8473
+ for (const [, entry] of _listenerMap) {
8474
+ ipcRenderer$2.removeListener(entry.channel, entry.wrapped);
8475
+ }
8476
+ _listenerMap.clear();
8394
8477
  ipcRenderer$2.removeAllListeners(LLM_STREAM_DELTA);
8395
8478
  ipcRenderer$2.removeAllListeners(LLM_STREAM_TOOL_CALL);
8396
8479
  ipcRenderer$2.removeAllListeners(LLM_STREAM_TOOL_RESULT);