@astralyn/pi 0.82.5 → 0.82.7

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.
Files changed (223) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +1 -1
  3. package/dist/cli/project-trust.d.ts.map +1 -1
  4. package/dist/cli/project-trust.js +4 -1
  5. package/dist/cli/project-trust.js.map +1 -1
  6. package/dist/cli/session-picker.d.ts.map +1 -1
  7. package/dist/cli/session-picker.js +11 -13
  8. package/dist/cli/session-picker.js.map +1 -1
  9. package/dist/core/bash-executor.d.ts.map +1 -1
  10. package/dist/core/bash-executor.js +4 -22
  11. package/dist/core/bash-executor.js.map +1 -1
  12. package/dist/core/extensions/index.d.ts +1 -1
  13. package/dist/core/extensions/index.d.ts.map +1 -1
  14. package/dist/core/extensions/index.js.map +1 -1
  15. package/dist/core/extensions/types.d.ts +32 -5
  16. package/dist/core/extensions/types.d.ts.map +1 -1
  17. package/dist/core/extensions/types.js.map +1 -1
  18. package/dist/core/session-manager.d.ts.map +1 -1
  19. package/dist/core/session-manager.js +2 -2
  20. package/dist/core/session-manager.js.map +1 -1
  21. package/dist/core/tools/bash.d.ts +1 -5
  22. package/dist/core/tools/bash.d.ts.map +1 -1
  23. package/dist/core/tools/bash.js +16 -41
  24. package/dist/core/tools/bash.js.map +1 -1
  25. package/dist/core/tools/edit.d.ts.map +1 -1
  26. package/dist/core/tools/edit.js +42 -11
  27. package/dist/core/tools/edit.js.map +1 -1
  28. package/dist/core/tools/find.d.ts.map +1 -1
  29. package/dist/core/tools/find.js +6 -7
  30. package/dist/core/tools/find.js.map +1 -1
  31. package/dist/core/tools/grep.d.ts.map +1 -1
  32. package/dist/core/tools/grep.js +17 -8
  33. package/dist/core/tools/grep.js.map +1 -1
  34. package/dist/core/tools/ls.d.ts.map +1 -1
  35. package/dist/core/tools/ls.js +3 -3
  36. package/dist/core/tools/ls.js.map +1 -1
  37. package/dist/core/tools/output-accumulator.d.ts +3 -13
  38. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  39. package/dist/core/tools/output-accumulator.js +6 -36
  40. package/dist/core/tools/output-accumulator.js.map +1 -1
  41. package/dist/core/tools/read.d.ts.map +1 -1
  42. package/dist/core/tools/read.js +4 -4
  43. package/dist/core/tools/read.js.map +1 -1
  44. package/dist/core/tools/render-utils.d.ts +7 -0
  45. package/dist/core/tools/render-utils.d.ts.map +1 -1
  46. package/dist/core/tools/render-utils.js +11 -0
  47. package/dist/core/tools/render-utils.js.map +1 -1
  48. package/dist/core/tools/write.d.ts.map +1 -1
  49. package/dist/core/tools/write.js +2 -3
  50. package/dist/core/tools/write.js.map +1 -1
  51. package/dist/extensions/deepwiki/render.d.ts.map +1 -1
  52. package/dist/extensions/deepwiki/render.js +34 -22
  53. package/dist/extensions/deepwiki/render.js.map +1 -1
  54. package/dist/extensions/plan/constants.d.ts +43 -6
  55. package/dist/extensions/plan/constants.d.ts.map +1 -1
  56. package/dist/extensions/plan/constants.js +51 -8
  57. package/dist/extensions/plan/constants.js.map +1 -1
  58. package/dist/extensions/plan/index.d.ts +12 -3
  59. package/dist/extensions/plan/index.d.ts.map +1 -1
  60. package/dist/extensions/plan/index.js +173 -35
  61. package/dist/extensions/plan/index.js.map +1 -1
  62. package/dist/extensions/plan/schema.d.ts +5 -0
  63. package/dist/extensions/plan/schema.d.ts.map +1 -1
  64. package/dist/extensions/plan/schema.js.map +1 -1
  65. package/dist/extensions/plan/state.d.ts +11 -2
  66. package/dist/extensions/plan/state.d.ts.map +1 -1
  67. package/dist/extensions/plan/state.js +31 -9
  68. package/dist/extensions/plan/state.js.map +1 -1
  69. package/dist/extensions/plan/storage.d.ts +11 -3
  70. package/dist/extensions/plan/storage.d.ts.map +1 -1
  71. package/dist/extensions/plan/storage.js +45 -20
  72. package/dist/extensions/plan/storage.js.map +1 -1
  73. package/dist/extensions/plan/view.d.ts +44 -0
  74. package/dist/extensions/plan/view.d.ts.map +1 -0
  75. package/dist/extensions/plan/view.js +149 -0
  76. package/dist/extensions/plan/view.js.map +1 -0
  77. package/dist/extensions/question/dialog.d.ts.map +1 -1
  78. package/dist/extensions/question/dialog.js +29 -10
  79. package/dist/extensions/question/dialog.js.map +1 -1
  80. package/dist/extensions/question/index.d.ts.map +1 -1
  81. package/dist/extensions/question/index.js +7 -2
  82. package/dist/extensions/question/index.js.map +1 -1
  83. package/dist/extensions/question/render.d.ts +4 -8
  84. package/dist/extensions/question/render.d.ts.map +1 -1
  85. package/dist/extensions/question/render.js +202 -29
  86. package/dist/extensions/question/render.js.map +1 -1
  87. package/dist/extensions/question/results.d.ts.map +1 -1
  88. package/dist/extensions/question/results.js +1 -0
  89. package/dist/extensions/question/results.js.map +1 -1
  90. package/dist/extensions/question/schema.d.ts.map +1 -1
  91. package/dist/extensions/question/schema.js +2 -2
  92. package/dist/extensions/question/schema.js.map +1 -1
  93. package/dist/extensions/question/types.d.ts +1 -0
  94. package/dist/extensions/question/types.d.ts.map +1 -1
  95. package/dist/extensions/question/types.js +1 -1
  96. package/dist/extensions/question/types.js.map +1 -1
  97. package/dist/extensions/router/stream.d.ts +1 -0
  98. package/dist/extensions/router/stream.d.ts.map +1 -1
  99. package/dist/extensions/router/stream.js +75 -0
  100. package/dist/extensions/router/stream.js.map +1 -1
  101. package/dist/extensions/subagent/activity.d.ts.map +1 -1
  102. package/dist/extensions/subagent/activity.js +25 -4
  103. package/dist/extensions/subagent/activity.js.map +1 -1
  104. package/dist/extensions/subagent/constants.d.ts +1 -0
  105. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  106. package/dist/extensions/subagent/constants.js +1 -0
  107. package/dist/extensions/subagent/constants.js.map +1 -1
  108. package/dist/extensions/subagent/index.d.ts.map +1 -1
  109. package/dist/extensions/subagent/index.js +16 -0
  110. package/dist/extensions/subagent/index.js.map +1 -1
  111. package/dist/extensions/subagent/render.d.ts.map +1 -1
  112. package/dist/extensions/subagent/render.js +352 -152
  113. package/dist/extensions/subagent/render.js.map +1 -1
  114. package/dist/extensions/subagent/resolve.d.ts.map +1 -1
  115. package/dist/extensions/subagent/resolve.js +13 -9
  116. package/dist/extensions/subagent/resolve.js.map +1 -1
  117. package/dist/extensions/subagent/retry.d.ts +17 -0
  118. package/dist/extensions/subagent/retry.d.ts.map +1 -0
  119. package/dist/extensions/subagent/retry.js +41 -0
  120. package/dist/extensions/subagent/retry.js.map +1 -0
  121. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  122. package/dist/extensions/subagent/runner.js +37 -7
  123. package/dist/extensions/subagent/runner.js.map +1 -1
  124. package/dist/extensions/subagent/schema.d.ts.map +1 -1
  125. package/dist/extensions/subagent/schema.js +2 -2
  126. package/dist/extensions/subagent/schema.js.map +1 -1
  127. package/dist/extensions/subagent/sdk-runner.d.ts +6 -0
  128. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  129. package/dist/extensions/subagent/sdk-runner.js +46 -24
  130. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  131. package/dist/extensions/subagent/types.d.ts +7 -0
  132. package/dist/extensions/subagent/types.d.ts.map +1 -1
  133. package/dist/extensions/subagent/types.js.map +1 -1
  134. package/dist/extensions/todo/constants.d.ts +17 -6
  135. package/dist/extensions/todo/constants.d.ts.map +1 -1
  136. package/dist/extensions/todo/constants.js +22 -9
  137. package/dist/extensions/todo/constants.js.map +1 -1
  138. package/dist/extensions/todo/index.d.ts +0 -14
  139. package/dist/extensions/todo/index.d.ts.map +1 -1
  140. package/dist/extensions/todo/index.js +13 -1
  141. package/dist/extensions/todo/index.js.map +1 -1
  142. package/dist/extensions/todo/schema.d.ts +53 -2
  143. package/dist/extensions/todo/schema.d.ts.map +1 -1
  144. package/dist/extensions/todo/schema.js +57 -8
  145. package/dist/extensions/todo/schema.js.map +1 -1
  146. package/dist/extensions/todo/state.d.ts +16 -5
  147. package/dist/extensions/todo/state.d.ts.map +1 -1
  148. package/dist/extensions/todo/state.js +874 -130
  149. package/dist/extensions/todo/state.js.map +1 -1
  150. package/dist/extensions/todo/view.d.ts +16 -1
  151. package/dist/extensions/todo/view.d.ts.map +1 -1
  152. package/dist/extensions/todo/view.js +428 -1
  153. package/dist/extensions/todo/view.js.map +1 -1
  154. package/dist/migrations.d.ts.map +1 -1
  155. package/dist/migrations.js +2 -1
  156. package/dist/migrations.js.map +1 -1
  157. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  158. package/dist/modes/interactive/components/armin.js +5 -0
  159. package/dist/modes/interactive/components/armin.js.map +1 -1
  160. package/dist/modes/interactive/components/bash-execution.d.ts +1 -0
  161. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  162. package/dist/modes/interactive/components/bash-execution.js +4 -2
  163. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  164. package/dist/modes/interactive/components/countdown-timer.d.ts +13 -6
  165. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  166. package/dist/modes/interactive/components/countdown-timer.js +54 -17
  167. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  168. package/dist/modes/interactive/components/extension-selector.d.ts +6 -1
  169. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/extension-selector.js +23 -11
  171. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  172. package/dist/modes/interactive/components/keybinding-hints.d.ts +11 -1
  173. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/keybinding-hints.js +56 -0
  175. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  176. package/dist/modes/interactive/components/session-selector.d.ts +3 -0
  177. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  178. package/dist/modes/interactive/components/session-selector.js +52 -2
  179. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  180. package/dist/modes/interactive/components/tool-execution.d.ts +10 -0
  181. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  182. package/dist/modes/interactive/components/tool-execution.js +139 -18
  183. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  184. package/dist/modes/interactive/components/tool-group.d.ts +1 -0
  185. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  186. package/dist/modes/interactive/components/tool-group.js +5 -0
  187. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  188. package/dist/modes/interactive/components/tree-selector.d.ts +10 -1
  189. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  190. package/dist/modes/interactive/components/tree-selector.js +55 -2
  191. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  192. package/dist/modes/interactive/interactive-mode.d.ts +5 -0
  193. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  194. package/dist/modes/interactive/interactive-mode.js +79 -19
  195. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  196. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  197. package/dist/modes/interactive/theme/theme.js +3 -2
  198. package/dist/modes/interactive/theme/theme.js.map +1 -1
  199. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  200. package/dist/modes/rpc/rpc-mode.js +8 -1
  201. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  202. package/dist/utils/paths.d.ts +6 -0
  203. package/dist/utils/paths.d.ts.map +1 -1
  204. package/dist/utils/paths.js +8 -0
  205. package/dist/utils/paths.js.map +1 -1
  206. package/docs/bundled/README.md +1 -0
  207. package/docs/bundled/extensions/deepwiki.md +1 -1
  208. package/docs/bundled/extensions/plan.md +13 -10
  209. package/docs/bundled/extensions/question.md +7 -5
  210. package/docs/bundled/extensions/router.md +3 -4
  211. package/docs/bundled/extensions/statusline.md +0 -1
  212. package/docs/bundled/extensions/subagent.md +5 -4
  213. package/docs/bundled/extensions/todo.md +9 -7
  214. package/docs/bundled/tool-presentation.md +17 -16
  215. package/docs/extensions.md +34 -5
  216. package/docs/rpc.md +1 -1
  217. package/docs/usage.md +1 -1
  218. package/npm-shrinkwrap.json +6 -6
  219. package/package.json +1 -1
  220. package/dist/utils/output-decoder.d.ts +0 -52
  221. package/dist/utils/output-decoder.d.ts.map +0 -1
  222. package/dist/utils/output-decoder.js +0 -134
  223. package/dist/utils/output-decoder.js.map +0 -1
@@ -186,6 +186,8 @@ export class InteractiveMode {
186
186
  onInputCallback;
187
187
  pendingUserInputs = [];
188
188
  activeStatusIndicator = undefined;
189
+ activeSelector = null;
190
+ activeSelectorCleanup = null;
189
191
  idleStatus = new IdleStatus();
190
192
  workingMessage = undefined;
191
193
  workingVisible = true;
@@ -1252,7 +1254,7 @@ export class InteractiveMode {
1252
1254
  if (result.cancelled) {
1253
1255
  return { cancelled: true };
1254
1256
  }
1255
- this.chatContainer.clear();
1257
+ this.clearChat();
1256
1258
  this.renderInitialMessages();
1257
1259
  if (result.editorText && !this.editor.getText().trim()) {
1258
1260
  this.editor.setText(result.editorText);
@@ -1331,14 +1333,34 @@ export class InteractiveMode {
1331
1333
  this.stop();
1332
1334
  process.exit(1);
1333
1335
  }
1336
+ disposeChatToolComponents() {
1337
+ for (const child of this.chatContainer.children) {
1338
+ if (child instanceof ToolExecutionComponent ||
1339
+ child instanceof ToolGroupComponent ||
1340
+ child instanceof ArminComponent ||
1341
+ child instanceof DaxnutsComponent) {
1342
+ child.dispose();
1343
+ }
1344
+ }
1345
+ }
1346
+ clearChat() {
1347
+ this.disposeChatToolComponents();
1348
+ this.chatContainer.clear();
1349
+ }
1350
+ clearPendingTools() {
1351
+ for (const component of this.pendingTools.values()) {
1352
+ component.dispose();
1353
+ }
1354
+ this.pendingTools.clear();
1355
+ }
1334
1356
  renderCurrentSessionState() {
1335
1357
  this.loadedResourcesContainer.clear();
1336
- this.chatContainer.clear();
1358
+ this.clearChat();
1337
1359
  this.pendingMessagesContainer.clear();
1338
1360
  this.compactionQueuedMessages = [];
1339
1361
  this.streamingComponent = undefined;
1340
1362
  this.streamingMessage = undefined;
1341
- this.pendingTools.clear();
1363
+ this.clearPendingTools();
1342
1364
  this.renderInitialMessages();
1343
1365
  }
1344
1366
  /**
@@ -1767,7 +1789,13 @@ export class InteractiveMode {
1767
1789
  opts?.signal?.removeEventListener("abort", onAbort);
1768
1790
  this.hideExtensionSelector();
1769
1791
  resolve(undefined);
1770
- }, { tui: this.ui, timeout: opts?.timeout, onToggleToolsExpanded: () => this.toggleToolOutputExpansion() });
1792
+ }, {
1793
+ tui: this.ui,
1794
+ timeout: opts?.timeout,
1795
+ subtitle: opts?.subtitle,
1796
+ cancelHint: opts?.cancelHint,
1797
+ onToggleToolsExpanded: () => this.toggleToolOutputExpansion(),
1798
+ });
1771
1799
  this.editorContainer.clear();
1772
1800
  this.editorContainer.addChild(this.extensionSelector);
1773
1801
  this.ui.setFocus(this.extensionSelector);
@@ -2320,7 +2348,7 @@ export class InteractiveMode {
2320
2348
  case "agent_start":
2321
2349
  this.agentRunActive = true;
2322
2350
  this.coalescingTerminal.setScrollbackPreservation(true);
2323
- this.pendingTools.clear();
2351
+ this.clearPendingTools();
2324
2352
  if (this.settingsManager.getShowTerminalProgress()) {
2325
2353
  this.ui.terminal.setProgress(true);
2326
2354
  }
@@ -2489,7 +2517,7 @@ export class InteractiveMode {
2489
2517
  this.streamingComponent = undefined;
2490
2518
  this.streamingMessage = undefined;
2491
2519
  }
2492
- this.pendingTools.clear();
2520
+ this.clearPendingTools();
2493
2521
  this.ui.requestRender();
2494
2522
  break;
2495
2523
  case "agent_settled":
@@ -2531,7 +2559,7 @@ export class InteractiveMode {
2531
2559
  }
2532
2560
  else {
2533
2561
  if (event.result) {
2534
- this.chatContainer.clear();
2562
+ this.clearChat();
2535
2563
  this.rebuildChatFromMessages();
2536
2564
  this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
2537
2565
  this.footer.invalidate();
@@ -2727,7 +2755,7 @@ export class InteractiveMode {
2727
2755
  }
2728
2756
  }
2729
2757
  renderSessionItems(items, options = {}) {
2730
- this.pendingTools.clear();
2758
+ this.clearPendingTools();
2731
2759
  const renderedPendingTools = new Map();
2732
2760
  // Cache-miss notices are not persisted; re-derive them from the full entry
2733
2761
  // list and re-inject them after the assistant messages that paid for them.
@@ -2876,7 +2904,7 @@ export class InteractiveMode {
2876
2904
  });
2877
2905
  }
2878
2906
  rebuildChatFromMessages() {
2879
- this.chatContainer.clear();
2907
+ this.clearChat();
2880
2908
  this.renderSessionEntries(this.sessionManager.buildContextEntries());
2881
2909
  }
2882
2910
  // =========================================================================
@@ -3168,7 +3196,7 @@ export class InteractiveMode {
3168
3196
  // Same reasoning as setToolsExpanded.
3169
3197
  this.coalescingTerminal.passNextFullRedraw();
3170
3198
  // Rebuild chat from session messages
3171
- this.chatContainer.clear();
3199
+ this.clearChat();
3172
3200
  this.rebuildChatFromMessages();
3173
3201
  // If streaming, re-add the streaming component with updated visibility and re-render
3174
3202
  if (this.streamingComponent && this.streamingMessage) {
@@ -3416,15 +3444,42 @@ export class InteractiveMode {
3416
3444
  * @param create Factory that receives a `done` callback and returns the component and focus target
3417
3445
  */
3418
3446
  showSelector(create) {
3447
+ this.activeSelectorCleanup?.();
3448
+ this.activeSelectorCleanup = null;
3449
+ this.activeSelector = null;
3450
+ let selector;
3451
+ let disposed = false;
3452
+ let closed = false;
3453
+ const dispose = () => {
3454
+ if (disposed || !selector)
3455
+ return;
3456
+ disposed = true;
3457
+ selector.dispose?.();
3458
+ };
3419
3459
  const done = () => {
3420
- this.editorContainer.clear();
3421
- this.editorContainer.addChild(this.editor);
3422
- this.ui.setFocus(this.editor);
3460
+ if (closed)
3461
+ return;
3462
+ closed = true;
3463
+ dispose();
3464
+ if (!selector || this.activeSelector === selector) {
3465
+ this.activeSelector = null;
3466
+ this.activeSelectorCleanup = null;
3467
+ this.editorContainer.clear();
3468
+ this.editorContainer.addChild(this.editor);
3469
+ this.ui.setFocus(this.editor);
3470
+ }
3423
3471
  };
3424
- const { component, focus } = create(done);
3472
+ const created = create(done);
3473
+ selector = created.component;
3474
+ if (closed) {
3475
+ dispose();
3476
+ return;
3477
+ }
3478
+ this.activeSelector = selector;
3479
+ this.activeSelectorCleanup = dispose;
3425
3480
  this.editorContainer.clear();
3426
- this.editorContainer.addChild(component);
3427
- this.ui.setFocus(focus);
3481
+ this.editorContainer.addChild(selector);
3482
+ this.ui.setFocus(created.focus);
3428
3483
  this.ui.requestRender();
3429
3484
  }
3430
3485
  showSettingsSelector() {
@@ -3524,7 +3579,7 @@ export class InteractiveMode {
3524
3579
  child.setHideThinkingBlock(hidden);
3525
3580
  }
3526
3581
  }
3527
- this.chatContainer.clear();
3582
+ this.clearChat();
3528
3583
  this.rebuildChatFromMessages();
3529
3584
  },
3530
3585
  onShowCacheMissNoticesChange: (shown) => {
@@ -3946,7 +4001,7 @@ export class InteractiveMode {
3946
4001
  return;
3947
4002
  }
3948
4003
  // Update UI
3949
- this.chatContainer.clear();
4004
+ this.clearChat();
3950
4005
  this.renderInitialMessages();
3951
4006
  if (result.editorText && !this.editor.getText().trim()) {
3952
4007
  this.editor.setText(result.editorText);
@@ -3969,7 +4024,7 @@ export class InteractiveMode {
3969
4024
  }, (entryId, label) => {
3970
4025
  this.sessionManager.appendLabelChange(entryId, label);
3971
4026
  this.ui.requestRender();
3972
- }, initialSelectedId, initialFilterMode);
4027
+ }, initialSelectedId, initialFilterMode, () => this.ui.requestRender());
3973
4028
  selector.onCopy = async (text) => {
3974
4029
  if (!text) {
3975
4030
  this.showError("Selected entry has no text to copy");
@@ -5076,12 +5131,17 @@ export class InteractiveMode {
5076
5131
  }
5077
5132
  }
5078
5133
  stop() {
5134
+ this.activeSelectorCleanup?.();
5135
+ this.activeSelectorCleanup = null;
5136
+ this.activeSelector = null;
5079
5137
  if (this.settingsManager.getShowTerminalProgress()) {
5080
5138
  this.ui.terminal.setProgress(false);
5081
5139
  }
5082
5140
  this.clearStatusIndicator();
5083
5141
  this.themeController.disableAutoSync();
5084
5142
  this.clearExtensionTerminalInputListeners();
5143
+ this.clearPendingTools();
5144
+ this.disposeChatToolComponents();
5085
5145
  this.footer.dispose();
5086
5146
  this.footerDataProvider.dispose();
5087
5147
  if (this.unsubscribe) {