lsd-pi 1.3.6 → 1.3.9

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 (126) hide show
  1. package/README.md +82 -0
  2. package/dist/cli.js +2 -1
  3. package/dist/lsd-settings-manager.d.ts +2 -0
  4. package/dist/lsd-settings-manager.js +5 -0
  5. package/dist/resource-loader.js +33 -3
  6. package/dist/resources/extensions/cache-timer/index.js +3 -2
  7. package/dist/resources/extensions/mcp-client/index.js +72 -4
  8. package/dist/resources/extensions/slash-commands/plan.js +5 -5
  9. package/dist/resources/extensions/usage/index.js +34 -2
  10. package/dist/resources/extensions/voice/index.js +1 -0
  11. package/dist/resources/extensions/voice/push-to-talk.js +2 -0
  12. package/dist/welcome-screen.js +2 -2
  13. package/package.json +1 -1
  14. package/packages/pi-coding-agent/dist/core/agent-session.context-usage.test.d.ts +2 -0
  15. package/packages/pi-coding-agent/dist/core/agent-session.context-usage.test.d.ts.map +1 -0
  16. package/packages/pi-coding-agent/dist/core/agent-session.context-usage.test.js +72 -0
  17. package/packages/pi-coding-agent/dist/core/agent-session.context-usage.test.js.map +1 -0
  18. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
  19. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  20. package/packages/pi-coding-agent/dist/core/agent-session.js +29 -2
  21. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  22. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  23. package/packages/pi-coding-agent/dist/core/extensions/runner.js +1 -0
  24. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  25. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
  26. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  27. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  28. package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.d.ts +2 -0
  29. package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.d.ts.map +1 -0
  30. package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.js +35 -0
  31. package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.js.map +1 -0
  32. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
  33. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  34. package/packages/pi-coding-agent/dist/core/settings-manager.js +12 -0
  35. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  36. package/packages/pi-coding-agent/dist/core/tool-priority.js +1 -1
  37. package/packages/pi-coding-agent/dist/core/tool-priority.js.map +1 -1
  38. package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts +5 -0
  39. package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts.map +1 -1
  40. package/packages/pi-coding-agent/dist/core/tools/edit-diff.js +21 -0
  41. package/packages/pi-coding-agent/dist/core/tools/edit-diff.js.map +1 -1
  42. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +16 -1
  43. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  44. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  45. package/packages/pi-coding-agent/dist/main.js +1 -0
  46. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  47. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js +12 -4
  48. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js.map +1 -1
  49. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +7 -5
  50. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
  51. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +86 -28
  52. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
  53. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +2 -0
  54. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  55. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +16 -10
  56. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  57. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  58. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  59. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +26 -4
  60. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  61. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +16 -1
  62. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  63. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +128 -13
  64. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  65. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts +1 -0
  66. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts.map +1 -1
  67. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js +48 -4
  68. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js.map +1 -1
  69. package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js +137 -6
  70. package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js.map +1 -1
  71. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  72. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +64 -15
  73. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  74. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.d.ts.map +1 -1
  75. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js +2 -1
  76. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -1
  77. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  78. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  79. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  80. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +5 -1
  81. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  82. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +73 -27
  83. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  84. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +4 -4
  85. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  86. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  87. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +3 -0
  88. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  89. package/packages/pi-coding-agent/package.json +1 -1
  90. package/packages/pi-coding-agent/src/core/agent-session.context-usage.test.ts +87 -0
  91. package/packages/pi-coding-agent/src/core/agent-session.ts +40 -2
  92. package/packages/pi-coding-agent/src/core/extensions/runner.ts +1 -0
  93. package/packages/pi-coding-agent/src/core/extensions/types.ts +3 -0
  94. package/packages/pi-coding-agent/src/core/settings-manager.collapse-tool-calls.test.ts +46 -0
  95. package/packages/pi-coding-agent/src/core/settings-manager.ts +18 -0
  96. package/packages/pi-coding-agent/src/core/tool-priority.ts +1 -1
  97. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +20 -0
  98. package/packages/pi-coding-agent/src/core/tools/edit-diff.ts +26 -0
  99. package/packages/pi-coding-agent/src/main.ts +1 -0
  100. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-summary-line.test.ts +14 -4
  101. package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +105 -28
  102. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +13 -6
  103. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +31 -4
  104. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +137 -14
  105. package/packages/pi-coding-agent/src/modes/interactive/components/tool-summary-line.ts +60 -4
  106. package/packages/pi-coding-agent/src/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.ts +174 -6
  107. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +73 -15
  108. package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +2 -1
  109. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
  110. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +76 -27
  111. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +4 -4
  112. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +4 -0
  113. package/packages/pi-tui/dist/components/editor.js +3 -3
  114. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  115. package/packages/pi-tui/src/components/editor.ts +3 -3
  116. package/pkg/dist/modes/interactive/theme/themes.js +4 -4
  117. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  118. package/pkg/package.json +1 -1
  119. package/src/resources/extensions/cache-timer/index.ts +3 -2
  120. package/src/resources/extensions/mcp-client/index.ts +83 -4
  121. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +16 -0
  122. package/src/resources/extensions/slash-commands/plan.ts +6 -6
  123. package/src/resources/extensions/usage/index.ts +40 -2
  124. package/src/resources/extensions/voice/index.ts +1 -0
  125. package/src/resources/extensions/voice/push-to-talk.ts +3 -0
  126. package/src/resources/extensions/voice/tests/push-to-talk.test.ts +6 -0
@@ -452,15 +452,15 @@ export class Editor implements Component, Focusable {
452
452
  const remaining = width - visibleWidth(indicator);
453
453
  result.push(this.borderColor(indicator + "─".repeat(Math.max(0, remaining))));
454
454
  } else if (this.bottomHint) {
455
- // Embed hint right-aligned in the bottom border: ─────── hint ─
455
+ // Embed hint at far right in bottom border: ─────────────── hint ─
456
456
  // Apply borderColor only to the dashes so the hint's own styling is preserved.
457
457
  const hintVisible = visibleWidth(this.bottomHint);
458
458
  const minDashes = 1;
459
459
  const separatorWidth = 1; // single space on each side of hint
460
460
  const totalFixed = hintVisible + separatorWidth * 2 + minDashes * 2;
461
461
  if (width >= totalFixed) {
462
- const leftDashes = Math.floor((width - hintVisible - separatorWidth * 2) * 0.75);
463
- const rightDashes = Math.max(minDashes, width - hintVisible - separatorWidth * 2 - leftDashes);
462
+ const rightDashes = minDashes;
463
+ const leftDashes = Math.max(minDashes, width - hintVisible - separatorWidth * 2 - rightDashes);
464
464
  const line =
465
465
  this.borderColor("─".repeat(leftDashes)) +
466
466
  " " +
@@ -69,8 +69,8 @@ const dark = {
69
69
  mdQuoteBorder: "gray",
70
70
  mdHr: "gray",
71
71
  mdListBullet: "accent",
72
- toolDiffAdded: "green",
73
- toolDiffRemoved: "red",
72
+ toolDiffAdded: "#4ade80",
73
+ toolDiffRemoved: "#fb7185",
74
74
  toolDiffContext: "gray",
75
75
  syntaxComment: "#6A9955",
76
76
  syntaxKeyword: "#569CD6",
@@ -157,8 +157,8 @@ const light = {
157
157
  mdQuoteBorder: "mediumGray",
158
158
  mdHr: "mediumGray",
159
159
  mdListBullet: "green",
160
- toolDiffAdded: "green",
161
- toolDiffRemoved: "red",
160
+ toolDiffAdded: "#15803d",
161
+ toolDiffRemoved: "#b91c1c",
162
162
  toolDiffContext: "mediumGray",
163
163
  syntaxComment: "#008000",
164
164
  syntaxKeyword: "#0000FF",
@@ -1 +1 @@
1
- {"version":3,"file":"themes.js","sourceRoot":"","sources":["../../../../src/modes/interactive/theme/themes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Built-in theme definitions.\n *\n * Each theme is a self-contained record of color values. Variable references\n * (e.g. \"accent\") are resolved against the `vars` map at load time by the\n * theme engine in theme.ts.\n *\n * To add a new built-in theme, add an entry to `builtinThemes` below.\n */\n\n// Re-use the ThemeJson type from the schema defined in theme.ts.\n// We import only the type to avoid circular runtime dependencies.\nimport type { ThemeJson } from \"./theme.js\";\n\n// ---------------------------------------------------------------------------\n// Dark theme\n// ---------------------------------------------------------------------------\n\nconst dark: ThemeJson = {\n\tname: \"dark\",\n\tvars: {\n\t\tcyan: \"#4a8cf7\",\n\t\tblue: \"#4a8cf7\",\n\t\tgreen: \"#b5bd68\",\n\t\tred: \"#cc6666\",\n\t\tyellow: \"#facc15\",\n\t\tviolet: \"#a78bfa\",\n\t\tgray: \"#bec8d6\",\n\t\tdimGray: \"#8793a3\",\n\t\tdarkGray: \"#505050\",\n\t\taccent: \"#60a5fa\",\n\t\tblueMuted: \"#1e3a8a\",\n\t\tblueLow: \"#2563eb\",\n\t\tblueMedium: \"#4a8cf7\",\n\t\tblueHigh: \"#60a5fa\",\n\t\tblueXhigh: \"#93c5fd\",\n\t\tselectedBg: \"#323640\",\n\t\tuserMsgBg: \"#272727\",\n\t\ttoolPendingBg: \"#1e2230\",\n\t\ttoolSuccessBg: \"#1a2330\",\n\t\ttoolErrorBg: \"#2a1e30\",\n\t\tcustomMsgBg: \"#2d2838\",\n\t},\n\tcolors: {\n\t\taccent: \"accent\",\n\t\tborder: \"blue\",\n\t\tborderAccent: \"cyan\",\n\t\tborderMuted: \"blue\",\n\t\tsuccess: \"green\",\n\t\terror: \"red\",\n\t\twarning: \"yellow\",\n\t\tviolet: \"violet\",\n\t\tmuted: \"gray\",\n\t\tdim: \"dimGray\",\n\t\ttext: \"\",\n\t\tthinkingText: \"gray\",\n\n\t\tselectedBg: \"selectedBg\",\n\t\tuserMessageBg: \"userMsgBg\",\n\t\tuserMessageText: \"\",\n\t\tcustomMessageBg: \"customMsgBg\",\n\t\tcustomMessageText: \"\",\n\t\tcustomMessageLabel: \"#9575cd\",\n\t\ttoolPendingBg: \"toolPendingBg\",\n\t\ttoolSuccessBg: \"toolSuccessBg\",\n\t\ttoolErrorBg: \"toolErrorBg\",\n\t\ttoolTitle: \"\",\n\t\ttoolOutput: \"gray\",\n\n\t\tmdHeading: \"#f0c674\",\n\t\tmdLink: \"#5a8aaa\",\n\t\tmdLinkUrl: \"dimGray\",\n\t\tmdCode: \"accent\",\n\t\tmdCodeBlock: \"green\",\n\t\tmdCodeBlockBorder: \"gray\",\n\t\tmdQuote: \"gray\",\n\t\tmdQuoteBorder: \"gray\",\n\t\tmdHr: \"gray\",\n\t\tmdListBullet: \"accent\",\n\n\t\ttoolDiffAdded: \"green\",\n\t\ttoolDiffRemoved: \"red\",\n\t\ttoolDiffContext: \"gray\",\n\n\t\tsyntaxComment: \"#6A9955\",\n\t\tsyntaxKeyword: \"#569CD6\",\n\t\tsyntaxFunction: \"#DCDCAA\",\n\t\tsyntaxVariable: \"#9CDCFE\",\n\t\tsyntaxString: \"#CE9178\",\n\t\tsyntaxNumber: \"#B5CEA8\",\n\t\tsyntaxType: \"#4EC9B0\",\n\t\tsyntaxOperator: \"#D4D4D4\",\n\t\tsyntaxPunctuation: \"#D4D4D4\",\n\n\t\tthinkingOff: \"blueMuted\",\n\t\tthinkingMinimal: \"blueLow\",\n\t\tthinkingLow: \"blueMedium\",\n\t\tthinkingMedium: \"blueHigh\",\n\t\tthinkingHigh: \"blueXhigh\",\n\t\tthinkingXhigh: \"cyan\",\n\n\t\tbashMode: \"accent\",\n\t},\n\texport: {\n\t\tpageBg: \"#18181e\",\n\t\tcardBg: \"#1e1e24\",\n\t\tinfoBg: \"#3c3728\",\n\t},\n};\n\n// ---------------------------------------------------------------------------\n// Light theme\n// ---------------------------------------------------------------------------\n\nconst light: ThemeJson = {\n\tname: \"light\",\n\tvars: {\n\t\tteal: \"#3b82f6\",\n\t\tblue: \"#547da7\",\n\t\tgreen: \"#588458\",\n\t\tred: \"#aa5555\",\n\t\tyellow: \"#eab308\",\n\t\twarning: \"#7a5a00\",\n\t\tviolet: \"#8b5cf6\",\n\t\tmediumGray: \"#6c6c6c\",\n\t\tdimGray: \"#767676\",\n\t\tlightGray: \"#b0b0b0\",\n\t\tblueMuted: \"#6b8fb8\",\n\t\tblueLow: \"#547da7\",\n\t\tblueMedium: \"#3b82f6\",\n\t\tblueHigh: \"#2563eb\",\n\t\tblueXhigh: \"#1d4ed8\",\n\t\tselectedBg: \"#d0d0e0\",\n\t\tuserMsgBg: \"#e8e8e8\",\n\t\ttoolPendingBg: \"#e8eaf0\",\n\t\ttoolSuccessBg: \"#e8f0f0\",\n\t\ttoolErrorBg: \"#f0e8ee\",\n\t\tcustomMsgBg: \"#ede7f6\",\n\t},\n\tcolors: {\n\t\taccent: \"teal\",\n\t\tborder: \"blue\",\n\t\tborderAccent: \"teal\",\n\t\tborderMuted: \"lightGray\",\n\t\tsuccess: \"green\",\n\t\terror: \"red\",\n\t\twarning: \"warning\",\n\t\tviolet: \"violet\",\n\t\tmuted: \"mediumGray\",\n\t\tdim: \"dimGray\",\n\t\ttext: \"\",\n\t\tthinkingText: \"mediumGray\",\n\n\t\tselectedBg: \"selectedBg\",\n\t\tuserMessageBg: \"userMsgBg\",\n\t\tuserMessageText: \"\",\n\t\tcustomMessageBg: \"customMsgBg\",\n\t\tcustomMessageText: \"\",\n\t\tcustomMessageLabel: \"#7e57c2\",\n\t\ttoolPendingBg: \"toolPendingBg\",\n\t\ttoolSuccessBg: \"toolSuccessBg\",\n\t\ttoolErrorBg: \"toolErrorBg\",\n\t\ttoolTitle: \"\",\n\t\ttoolOutput: \"mediumGray\",\n\n\t\tmdHeading: \"yellow\",\n\t\tmdLink: \"blue\",\n\t\tmdLinkUrl: \"dimGray\",\n\t\tmdCode: \"teal\",\n\t\tmdCodeBlock: \"green\",\n\t\tmdCodeBlockBorder: \"mediumGray\",\n\t\tmdQuote: \"mediumGray\",\n\t\tmdQuoteBorder: \"mediumGray\",\n\t\tmdHr: \"mediumGray\",\n\t\tmdListBullet: \"green\",\n\n\t\ttoolDiffAdded: \"green\",\n\t\ttoolDiffRemoved: \"red\",\n\t\ttoolDiffContext: \"mediumGray\",\n\n\t\tsyntaxComment: \"#008000\",\n\t\tsyntaxKeyword: \"#0000FF\",\n\t\tsyntaxFunction: \"#795E26\",\n\t\tsyntaxVariable: \"#001080\",\n\t\tsyntaxString: \"#A31515\",\n\t\tsyntaxNumber: \"#098658\",\n\t\tsyntaxType: \"#267F99\",\n\t\tsyntaxOperator: \"#000000\",\n\t\tsyntaxPunctuation: \"#000000\",\n\n\t\tthinkingOff: \"blueMuted\",\n\t\tthinkingMinimal: \"blueLow\",\n\t\tthinkingLow: \"blueMedium\",\n\t\tthinkingMedium: \"teal\",\n\t\tthinkingHigh: \"blueHigh\",\n\t\tthinkingXhigh: \"blueXhigh\",\n\n\t\tbashMode: \"accent\",\n\t},\n\texport: {\n\t\tpageBg: \"#f8f8f8\",\n\t\tcardBg: \"#ffffff\",\n\t\tinfoBg: \"#fffae6\",\n\t},\n};\n\n// ---------------------------------------------------------------------------\n// Export\n// ---------------------------------------------------------------------------\n\nexport const builtinThemes: Record<string, ThemeJson> = { dark, light };\n"]}
1
+ {"version":3,"file":"themes.js","sourceRoot":"","sources":["../../../../src/modes/interactive/theme/themes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Built-in theme definitions.\n *\n * Each theme is a self-contained record of color values. Variable references\n * (e.g. \"accent\") are resolved against the `vars` map at load time by the\n * theme engine in theme.ts.\n *\n * To add a new built-in theme, add an entry to `builtinThemes` below.\n */\n\n// Re-use the ThemeJson type from the schema defined in theme.ts.\n// We import only the type to avoid circular runtime dependencies.\nimport type { ThemeJson } from \"./theme.js\";\n\n// ---------------------------------------------------------------------------\n// Dark theme\n// ---------------------------------------------------------------------------\n\nconst dark: ThemeJson = {\n\tname: \"dark\",\n\tvars: {\n\t\tcyan: \"#4a8cf7\",\n\t\tblue: \"#4a8cf7\",\n\t\tgreen: \"#b5bd68\",\n\t\tred: \"#cc6666\",\n\t\tyellow: \"#facc15\",\n\t\tviolet: \"#a78bfa\",\n\t\tgray: \"#bec8d6\",\n\t\tdimGray: \"#8793a3\",\n\t\tdarkGray: \"#505050\",\n\t\taccent: \"#60a5fa\",\n\t\tblueMuted: \"#1e3a8a\",\n\t\tblueLow: \"#2563eb\",\n\t\tblueMedium: \"#4a8cf7\",\n\t\tblueHigh: \"#60a5fa\",\n\t\tblueXhigh: \"#93c5fd\",\n\t\tselectedBg: \"#323640\",\n\t\tuserMsgBg: \"#272727\",\n\t\ttoolPendingBg: \"#1e2230\",\n\t\ttoolSuccessBg: \"#1a2330\",\n\t\ttoolErrorBg: \"#2a1e30\",\n\t\tcustomMsgBg: \"#2d2838\",\n\t},\n\tcolors: {\n\t\taccent: \"accent\",\n\t\tborder: \"blue\",\n\t\tborderAccent: \"cyan\",\n\t\tborderMuted: \"blue\",\n\t\tsuccess: \"green\",\n\t\terror: \"red\",\n\t\twarning: \"yellow\",\n\t\tviolet: \"violet\",\n\t\tmuted: \"gray\",\n\t\tdim: \"dimGray\",\n\t\ttext: \"\",\n\t\tthinkingText: \"gray\",\n\n\t\tselectedBg: \"selectedBg\",\n\t\tuserMessageBg: \"userMsgBg\",\n\t\tuserMessageText: \"\",\n\t\tcustomMessageBg: \"customMsgBg\",\n\t\tcustomMessageText: \"\",\n\t\tcustomMessageLabel: \"#9575cd\",\n\t\ttoolPendingBg: \"toolPendingBg\",\n\t\ttoolSuccessBg: \"toolSuccessBg\",\n\t\ttoolErrorBg: \"toolErrorBg\",\n\t\ttoolTitle: \"\",\n\t\ttoolOutput: \"gray\",\n\n\t\tmdHeading: \"#f0c674\",\n\t\tmdLink: \"#5a8aaa\",\n\t\tmdLinkUrl: \"dimGray\",\n\t\tmdCode: \"accent\",\n\t\tmdCodeBlock: \"green\",\n\t\tmdCodeBlockBorder: \"gray\",\n\t\tmdQuote: \"gray\",\n\t\tmdQuoteBorder: \"gray\",\n\t\tmdHr: \"gray\",\n\t\tmdListBullet: \"accent\",\n\n\t\ttoolDiffAdded: \"#4ade80\",\n\t\ttoolDiffRemoved: \"#fb7185\",\n\t\ttoolDiffContext: \"gray\",\n\n\t\tsyntaxComment: \"#6A9955\",\n\t\tsyntaxKeyword: \"#569CD6\",\n\t\tsyntaxFunction: \"#DCDCAA\",\n\t\tsyntaxVariable: \"#9CDCFE\",\n\t\tsyntaxString: \"#CE9178\",\n\t\tsyntaxNumber: \"#B5CEA8\",\n\t\tsyntaxType: \"#4EC9B0\",\n\t\tsyntaxOperator: \"#D4D4D4\",\n\t\tsyntaxPunctuation: \"#D4D4D4\",\n\n\t\tthinkingOff: \"blueMuted\",\n\t\tthinkingMinimal: \"blueLow\",\n\t\tthinkingLow: \"blueMedium\",\n\t\tthinkingMedium: \"blueHigh\",\n\t\tthinkingHigh: \"blueXhigh\",\n\t\tthinkingXhigh: \"cyan\",\n\n\t\tbashMode: \"accent\",\n\t},\n\texport: {\n\t\tpageBg: \"#18181e\",\n\t\tcardBg: \"#1e1e24\",\n\t\tinfoBg: \"#3c3728\",\n\t},\n};\n\n// ---------------------------------------------------------------------------\n// Light theme\n// ---------------------------------------------------------------------------\n\nconst light: ThemeJson = {\n\tname: \"light\",\n\tvars: {\n\t\tteal: \"#3b82f6\",\n\t\tblue: \"#547da7\",\n\t\tgreen: \"#588458\",\n\t\tred: \"#aa5555\",\n\t\tyellow: \"#eab308\",\n\t\twarning: \"#7a5a00\",\n\t\tviolet: \"#8b5cf6\",\n\t\tmediumGray: \"#6c6c6c\",\n\t\tdimGray: \"#767676\",\n\t\tlightGray: \"#b0b0b0\",\n\t\tblueMuted: \"#6b8fb8\",\n\t\tblueLow: \"#547da7\",\n\t\tblueMedium: \"#3b82f6\",\n\t\tblueHigh: \"#2563eb\",\n\t\tblueXhigh: \"#1d4ed8\",\n\t\tselectedBg: \"#d0d0e0\",\n\t\tuserMsgBg: \"#e8e8e8\",\n\t\ttoolPendingBg: \"#e8eaf0\",\n\t\ttoolSuccessBg: \"#e8f0f0\",\n\t\ttoolErrorBg: \"#f0e8ee\",\n\t\tcustomMsgBg: \"#ede7f6\",\n\t},\n\tcolors: {\n\t\taccent: \"teal\",\n\t\tborder: \"blue\",\n\t\tborderAccent: \"teal\",\n\t\tborderMuted: \"lightGray\",\n\t\tsuccess: \"green\",\n\t\terror: \"red\",\n\t\twarning: \"warning\",\n\t\tviolet: \"violet\",\n\t\tmuted: \"mediumGray\",\n\t\tdim: \"dimGray\",\n\t\ttext: \"\",\n\t\tthinkingText: \"mediumGray\",\n\n\t\tselectedBg: \"selectedBg\",\n\t\tuserMessageBg: \"userMsgBg\",\n\t\tuserMessageText: \"\",\n\t\tcustomMessageBg: \"customMsgBg\",\n\t\tcustomMessageText: \"\",\n\t\tcustomMessageLabel: \"#7e57c2\",\n\t\ttoolPendingBg: \"toolPendingBg\",\n\t\ttoolSuccessBg: \"toolSuccessBg\",\n\t\ttoolErrorBg: \"toolErrorBg\",\n\t\ttoolTitle: \"\",\n\t\ttoolOutput: \"mediumGray\",\n\n\t\tmdHeading: \"yellow\",\n\t\tmdLink: \"blue\",\n\t\tmdLinkUrl: \"dimGray\",\n\t\tmdCode: \"teal\",\n\t\tmdCodeBlock: \"green\",\n\t\tmdCodeBlockBorder: \"mediumGray\",\n\t\tmdQuote: \"mediumGray\",\n\t\tmdQuoteBorder: \"mediumGray\",\n\t\tmdHr: \"mediumGray\",\n\t\tmdListBullet: \"green\",\n\n\t\ttoolDiffAdded: \"#15803d\",\n\t\ttoolDiffRemoved: \"#b91c1c\",\n\t\ttoolDiffContext: \"mediumGray\",\n\n\t\tsyntaxComment: \"#008000\",\n\t\tsyntaxKeyword: \"#0000FF\",\n\t\tsyntaxFunction: \"#795E26\",\n\t\tsyntaxVariable: \"#001080\",\n\t\tsyntaxString: \"#A31515\",\n\t\tsyntaxNumber: \"#098658\",\n\t\tsyntaxType: \"#267F99\",\n\t\tsyntaxOperator: \"#000000\",\n\t\tsyntaxPunctuation: \"#000000\",\n\n\t\tthinkingOff: \"blueMuted\",\n\t\tthinkingMinimal: \"blueLow\",\n\t\tthinkingLow: \"blueMedium\",\n\t\tthinkingMedium: \"teal\",\n\t\tthinkingHigh: \"blueHigh\",\n\t\tthinkingXhigh: \"blueXhigh\",\n\n\t\tbashMode: \"accent\",\n\t},\n\texport: {\n\t\tpageBg: \"#f8f8f8\",\n\t\tcardBg: \"#ffffff\",\n\t\tinfoBg: \"#fffae6\",\n\t},\n};\n\n// ---------------------------------------------------------------------------\n// Export\n// ---------------------------------------------------------------------------\n\nexport const builtinThemes: Record<string, ThemeJson> = { dark, light };\n"]}
package/pkg/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lsd-pi",
3
- "version": "1.3.6",
3
+ "version": "1.3.9",
4
4
  "piConfig": {
5
5
  "name": "lsd",
6
6
  "configDir": ".lsd"
@@ -22,6 +22,7 @@ const IS_CACHE_TIMER_FORCED_OFF = process.env.LSD_DISABLE_CACHE_TIMER === "1" ||
22
22
 
23
23
  // ANSI color codes for timer display
24
24
  const ANSI_RESET = "\x1b[0m";
25
+ const ANSI_GREEN = "\x1b[32m";
25
26
  const ANSI_YELLOW = "\x1b[33m";
26
27
  const ANSI_RED = "\x1b[31m";
27
28
 
@@ -68,8 +69,8 @@ function formatElapsed(ms: number): string {
68
69
  // 5–10 minutes: yellow
69
70
  return `${ANSI_YELLOW}⏱ ${time}${ANSI_RESET}`;
70
71
  }
71
- // Under 5 minutes: plain (inherits footer dim styling)
72
- return `⏱ ${time}`;
72
+ // Under 5 minutes: green
73
+ return `${ANSI_GREEN}⏱ ${time}${ANSI_RESET}`;
73
74
  }
74
75
 
75
76
  export default function cacheTimerExtension(pi: ExtensionAPI) {
@@ -62,6 +62,14 @@ interface McpState {
62
62
  const connections = new Map<string, ManagedConnection>();
63
63
  let configCache: McpServerConfig[] | null = null;
64
64
  const toolCache = new Map<string, McpToolSchema[]>();
65
+ let warmupPromise: Promise<McpWarmupResult[]> | null = null;
66
+
67
+ interface McpWarmupResult {
68
+ name: string;
69
+ status: "connected" | "error";
70
+ toolCount?: number;
71
+ error?: string;
72
+ }
65
73
 
66
74
  const MCP_STATE_PATH = join(process.cwd(), ".lsd", "mcp-state.json");
67
75
 
@@ -263,6 +271,49 @@ async function getOrConnect(name: string, signal?: AbortSignal): Promise<Client>
263
271
  return client;
264
272
  }
265
273
 
274
+ async function warmupEnabledServers(): Promise<McpWarmupResult[]> {
275
+ if (warmupPromise) return warmupPromise;
276
+
277
+ warmupPromise = (async () => {
278
+ const enabledServers = readConfigs().filter((server) => server.enabled);
279
+ if (enabledServers.length === 0) return [];
280
+
281
+ const results = await Promise.allSettled(enabledServers.map(async (server) => {
282
+ const client = await getOrConnect(server.name);
283
+ const result = await client.listTools(undefined, { timeout: 30000 });
284
+ const tools: McpToolSchema[] = (result.tools ?? []).map((tool) => ({
285
+ name: tool.name,
286
+ description: tool.description ?? "",
287
+ inputSchema: tool.inputSchema as Record<string, unknown> | undefined,
288
+ }));
289
+ toolCache.set(server.name, tools);
290
+ return {
291
+ name: server.name,
292
+ status: "connected" as const,
293
+ toolCount: tools.length,
294
+ };
295
+ }));
296
+
297
+ return results.map((result, index) => {
298
+ if (result.status === "fulfilled") {
299
+ return result.value;
300
+ }
301
+
302
+ return {
303
+ name: enabledServers[index]?.name ?? `server-${index + 1}`,
304
+ status: "error" as const,
305
+ error: result.reason instanceof Error ? result.reason.message : String(result.reason),
306
+ };
307
+ });
308
+ })();
309
+
310
+ try {
311
+ return await warmupPromise;
312
+ } finally {
313
+ warmupPromise = null;
314
+ }
315
+ }
316
+
266
317
  async function closeAll(): Promise<void> {
267
318
  const closing = Array.from(connections.entries()).map(async ([name, conn]) => {
268
319
  try {
@@ -277,6 +328,7 @@ async function closeAll(): Promise<void> {
277
328
  }
278
329
 
279
330
  async function reloadMcpState(): Promise<void> {
331
+ warmupPromise = null;
280
332
  await closeAll();
281
333
  configCache = null;
282
334
  }
@@ -402,6 +454,14 @@ async function handleMcpCommand(args: string, ctx: ExtensionCommandContext): Pro
402
454
  const action = enabled ? "enabled" : "disabled";
403
455
  const changeText = result.changed ? action : `already ${action}`;
404
456
  ctx.ui.notify(`MCP server ${result.canonicalName} ${changeText}.`, "info");
457
+
458
+ if (enabled) {
459
+ const warmupResults = await warmupEnabledServers();
460
+ const warmupResult = warmupResults.find((entry) => entry.name === result.canonicalName);
461
+ if (warmupResult?.status === "error") {
462
+ ctx.ui.notify(`Failed to connect ${result.canonicalName}: ${warmupResult.error}`, "error");
463
+ }
464
+ }
405
465
  } catch (error) {
406
466
  const message = error instanceof Error ? error.message : String(error);
407
467
  ctx.ui.notify(message, "error");
@@ -412,7 +472,12 @@ async function handleMcpCommand(args: string, ctx: ExtensionCommandContext): Pro
412
472
  if (subcommand === "reload") {
413
473
  await reloadMcpState();
414
474
  const servers = readConfigs();
415
- ctx.ui.notify(`Reloaded MCP config ${servers.length} server(s) available.`, "info");
475
+ const warmupResults = await warmupEnabledServers();
476
+ const failed = warmupResults.filter((entry) => entry.status === "error");
477
+ const summary = failed.length > 0
478
+ ? `Reloaded MCP config — ${servers.length} server(s) available, ${failed.length} failed to connect.`
479
+ : `Reloaded MCP config — ${servers.length} server(s) available.`;
480
+ ctx.ui.notify(summary, failed.length > 0 ? "warning" : "info");
416
481
  return;
417
482
  }
418
483
 
@@ -733,17 +798,31 @@ export default function(pi: ExtensionAPI) {
733
798
 
734
799
  pi.on("session_start", async (_event, ctx) => {
735
800
  const servers = readConfigs();
801
+ const enabledServers = servers.filter((server) => server.enabled);
736
802
  if (servers.length > 0) {
737
- ctx.ui.notify(`MCP client ready — ${servers.filter((server) => server.enabled).length}/${servers.length} server(s) enabled`, "info");
803
+ ctx.ui.notify(`MCP client ready — ${enabledServers.length}/${servers.length} server(s) enabled`, "info");
738
804
  }
805
+ if (enabledServers.length === 0) return;
806
+
807
+ void warmupEnabledServers().then((results) => {
808
+ const failed = results.filter((entry) => entry.status === "error");
809
+ if (failed.length > 0) {
810
+ const failureSummary = failed.map((entry) => `${entry.name}: ${entry.error}`).join("; ");
811
+ ctx.ui.notify(`MCP autoconnect partial failure — ${failureSummary}`, "warning");
812
+ }
813
+ }).catch((error) => {
814
+ const message = error instanceof Error ? error.message : String(error);
815
+ ctx.ui.notify(`MCP autoconnect failed: ${message}`, "warning");
816
+ });
739
817
  });
740
818
 
741
819
  pi.on("session_shutdown", async () => {
820
+ warmupPromise = null;
742
821
  await closeAll();
743
822
  });
744
823
 
745
824
  pi.on("session_switch", async () => {
746
- await closeAll();
747
- configCache = null;
825
+ await reloadMcpState();
826
+ void warmupEnabledServers();
748
827
  });
749
828
  }
@@ -53,3 +53,19 @@ test("#3029: getOrConnect normalizes name for connection cache lookup", () => {
53
53
  "getOrConnect should use config.name (canonical) as the connections cache key",
54
54
  );
55
55
  });
56
+
57
+ test("enabled MCP servers are warmed up on session start", () => {
58
+ assert.match(
59
+ source,
60
+ /pi\.on\("session_start", async \(_event, ctx\) => {[\s\S]*?warmupEnabledServers\(/,
61
+ "session_start should trigger MCP autoconnect warmup for enabled servers",
62
+ );
63
+ });
64
+
65
+ test("warmupEnabledServers preloads tool schemas during autoconnect", () => {
66
+ assert.match(
67
+ source,
68
+ /async function warmupEnabledServers\([\s\S]*?client\.listTools\(undefined, \{ timeout: 30000 \}\)[\s\S]*?toolCache\.set\(/,
69
+ "warmupEnabledServers should list tools and populate tool cache during startup",
70
+ );
71
+ });
@@ -191,8 +191,8 @@ function readAutoSwitchPlanModelSetting(): boolean {
191
191
  const settingsPath = join(getAgentDir(), "settings.json");
192
192
  if (!existsSync(settingsPath)) return false;
193
193
  const raw = readFileSync(settingsPath, "utf-8");
194
- const parsed = JSON.parse(raw) as { autoSwitchPlanModel?: unknown };
195
- return parsed.autoSwitchPlanModel === true;
194
+ const parsed = JSON.parse(raw) as { planModeAutoSwitchModel?: unknown };
195
+ return parsed.planModeAutoSwitchModel === true;
196
196
  } catch {
197
197
  return false;
198
198
  }
@@ -418,10 +418,10 @@ async function approvePlan(
418
418
  permissionMode: RestorablePermissionMode,
419
419
  executeWithSubagent = false,
420
420
  ): Promise<void> {
421
- const reasoningModel = parseQualifiedModelRef(readPlanModeReasoningModel());
422
- if (reasoningModel) {
423
- await setModelIfNeeded(pi, ctx, reasoningModel);
424
- }
421
+ // Do NOT switch to reasoning model during execution.
422
+ // The reasoning model is only for plan-mode investigation, not execution.
423
+ // If a coding model is configured and we're using a subagent, the explicit
424
+ // model="<planModeCodingModel>" in the kickoff message will handle it.
425
425
 
426
426
  state = {
427
427
  ...state,
@@ -75,6 +75,8 @@ type UsageRow = {
75
75
  cacheWrite: number;
76
76
  total: number;
77
77
  cost: number;
78
+ totalDurationMs: number;
79
+ totalOutputForSpeed: number;
78
80
  };
79
81
 
80
82
  type UsageReport = {
@@ -313,6 +315,7 @@ function collectUsage(sessionFiles: string[], startMs: number, endMs: number, sc
313
315
  let projectLabel = basename(file);
314
316
  let headerResolved = false;
315
317
  let currentModel = "";
318
+ let lastUserTimestamp = 0;
316
319
 
317
320
  const raw = readFileSync(file, "utf-8");
318
321
  for (const line of raw.split("\n")) {
@@ -367,6 +370,8 @@ function collectUsage(sessionFiles: string[], startMs: number, endMs: number, sc
367
370
  cacheWrite: 0,
368
371
  total: 0,
369
372
  cost: 0,
373
+ totalDurationMs: 0,
374
+ totalOutputForSpeed: 0,
370
375
  };
371
376
 
372
377
  existing.messages += 1;
@@ -376,10 +381,27 @@ function collectUsage(sessionFiles: string[], startMs: number, endMs: number, sc
376
381
  existing.cacheWrite += cacheWrite;
377
382
  existing.total += total;
378
383
  existing.cost += cost;
384
+
385
+ // Track tok/sec: use preceding user message timestamp
386
+ if (output > 0 && lastUserTimestamp > 0) {
387
+ const durationMs = timestamp - lastUserTimestamp;
388
+ if (durationMs > 0) {
389
+ existing.totalDurationMs += durationMs;
390
+ existing.totalOutputForSpeed += output;
391
+ }
392
+ }
393
+
379
394
  rows.set(key, existing);
380
395
  } else if (message.role === "user") {
381
396
  const timestamp = Number(message.timestamp ?? 0);
382
- if (!timestamp || timestamp < startMs || timestamp >= endMs) continue;
397
+ if (!timestamp) continue;
398
+
399
+ // Always track last user timestamp for tok/sec calculation,
400
+ // even if this user message is outside the time range
401
+ // (the assistant response may still be within range).
402
+ lastUserTimestamp = timestamp;
403
+
404
+ if (timestamp < startMs || timestamp >= endMs) continue;
383
405
 
384
406
  matchedUserPrompts++;
385
407
  const model = currentModel;
@@ -397,6 +419,8 @@ function collectUsage(sessionFiles: string[], startMs: number, endMs: number, sc
397
419
  cacheWrite: 0,
398
420
  total: 0,
399
421
  cost: 0,
422
+ totalDurationMs: 0,
423
+ totalOutputForSpeed: 0,
400
424
  };
401
425
 
402
426
  existing.userPrompts += 1;
@@ -431,9 +455,11 @@ function collectUsage(sessionFiles: string[], startMs: number, endMs: number, sc
431
455
  acc.cacheWrite += row.cacheWrite;
432
456
  acc.total += row.total;
433
457
  acc.cost += row.cost;
458
+ acc.totalDurationMs += row.totalDurationMs;
459
+ acc.totalOutputForSpeed += row.totalOutputForSpeed;
434
460
  return acc;
435
461
  },
436
- { messages: 0, userPrompts: 0, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0, cost: 0 },
462
+ { messages: 0, userPrompts: 0, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0, cost: 0, totalDurationMs: 0, totalOutputForSpeed: 0 },
437
463
  );
438
464
 
439
465
  return {
@@ -448,6 +474,11 @@ function collectUsage(sessionFiles: string[], startMs: number, endMs: number, sc
448
474
  };
449
475
  }
450
476
 
477
+ function formatSpeed(totalDurationMs: number, totalOutputForSpeed: number): string {
478
+ if (totalDurationMs <= 0) return "—";
479
+ return Math.round(totalOutputForSpeed / (totalDurationMs / 1000)).toLocaleString();
480
+ }
481
+
451
482
  function renderTable(report: UsageReport): string {
452
483
  const firstColumnHeader = report.groupBy === "project"
453
484
  ? "project"
@@ -465,8 +496,11 @@ function renderTable(report: UsageReport): string {
465
496
  write: formatInt(row.cacheWrite),
466
497
  total: formatInt(row.total),
467
498
  cost: formatCost(row.cost),
499
+ speed: formatSpeed(row.totalDurationMs, row.totalOutputForSpeed),
468
500
  }));
469
501
 
502
+ const totalsSpeed = formatSpeed(report.totals.totalDurationMs, report.totals.totalOutputForSpeed);
503
+
470
504
  const widths = {
471
505
  label: Math.max(firstColumnHeader.length, ...displayRows.map((row) => row.label.length), 5),
472
506
  userPrompts: Math.max(11, ...displayRows.map((row) => row.userPrompts.length), String(report.totals.userPrompts).length),
@@ -477,6 +511,7 @@ function renderTable(report: UsageReport): string {
477
511
  write: Math.max(5, ...displayRows.map((row) => row.write.length), formatInt(report.totals.cacheWrite).length),
478
512
  total: Math.max(5, ...displayRows.map((row) => row.total.length), formatInt(report.totals.total).length),
479
513
  cost: Math.max(7, ...displayRows.map((row) => row.cost.length), formatCost(report.totals.cost).length),
514
+ speed: Math.max(5, ...displayRows.map((row) => row.speed.length), totalsSpeed.length),
480
515
  };
481
516
 
482
517
  const header = [
@@ -489,6 +524,7 @@ function renderTable(report: UsageReport): string {
489
524
  "write".padStart(widths.write),
490
525
  "total".padStart(widths.total),
491
526
  "cost".padStart(widths.cost),
527
+ "tok/s".padStart(widths.speed),
492
528
  ].join(" ");
493
529
 
494
530
  const divider = "-".repeat(header.length);
@@ -502,6 +538,7 @@ function renderTable(report: UsageReport): string {
502
538
  row.write.padStart(widths.write),
503
539
  row.total.padStart(widths.total),
504
540
  row.cost.padStart(widths.cost),
541
+ row.speed.padStart(widths.speed),
505
542
  ].join(" "));
506
543
 
507
544
  const totalsLine = [
@@ -514,6 +551,7 @@ function renderTable(report: UsageReport): string {
514
551
  formatInt(report.totals.cacheWrite).padStart(widths.write),
515
552
  formatInt(report.totals.total).padStart(widths.total),
516
553
  formatCost(report.totals.cost).padStart(widths.cost),
554
+ totalsSpeed.padStart(widths.speed),
517
555
  ].join(" ");
518
556
 
519
557
  return [header, divider, ...body, divider, totalsLine].join("\n");
@@ -303,6 +303,7 @@ export default function(pi: ExtensionAPI) {
303
303
  activationMode,
304
304
  editorText: ctx.ui.getEditorText(),
305
305
  holdToTalkSupported: isKittyProtocolActive(),
306
+ isEditorFocused: ctx.ui.isEditorFocused(),
306
307
  onUnsupported: () => {
307
308
  if (holdToTalkUnsupportedNotified) return;
308
309
  holdToTalkUnsupportedNotified = true;
@@ -8,6 +8,7 @@ export interface PushToTalkState {
8
8
  activationMode: VoiceActivationMode | null;
9
9
  editorText: string;
10
10
  holdToTalkSupported: boolean;
11
+ isEditorFocused: boolean;
11
12
  onUnsupported?(): void;
12
13
  startPushToTalk(): void | Promise<void>;
13
14
  stopVoice(): void | Promise<void>;
@@ -16,6 +17,8 @@ export interface PushToTalkState {
16
17
  export function handlePushToTalkInput(data: string, state: PushToTalkState): ReturnType<TerminalInputHandler> {
17
18
  if (!matchesKey(data, Key.space)) return undefined;
18
19
 
20
+ if (!state.isEditorFocused) return undefined;
21
+
19
22
  if (isKeyRelease(data)) {
20
23
  if (state.activationMode === "push-to-talk") {
21
24
  void Promise.resolve(state.stopVoice());
@@ -15,6 +15,7 @@ describe("voice push-to-talk handler", () => {
15
15
  activationMode: null,
16
16
  editorText: "",
17
17
  holdToTalkSupported: true,
18
+ isEditorFocused: true,
18
19
  startPushToTalk: () => { startCalls += 1; },
19
20
  stopVoice: () => { stopCalls += 1; },
20
21
  });
@@ -32,6 +33,7 @@ describe("voice push-to-talk handler", () => {
32
33
  activationMode: null,
33
34
  editorText: "hello",
34
35
  holdToTalkSupported: true,
36
+ isEditorFocused: true,
35
37
  startPushToTalk: () => { startCalls += 1; },
36
38
  stopVoice: () => { },
37
39
  });
@@ -48,6 +50,7 @@ describe("voice push-to-talk handler", () => {
48
50
  activationMode: "push-to-talk",
49
51
  editorText: "",
50
52
  holdToTalkSupported: true,
53
+ isEditorFocused: true,
51
54
  startPushToTalk: () => { startCalls += 1; },
52
55
  stopVoice: () => { },
53
56
  });
@@ -64,6 +67,7 @@ describe("voice push-to-talk handler", () => {
64
67
  activationMode: "push-to-talk",
65
68
  editorText: "",
66
69
  holdToTalkSupported: true,
70
+ isEditorFocused: true,
67
71
  startPushToTalk: () => { },
68
72
  stopVoice: () => { stopCalls += 1; },
69
73
  });
@@ -80,6 +84,7 @@ describe("voice push-to-talk handler", () => {
80
84
  activationMode: "toggle",
81
85
  editorText: "",
82
86
  holdToTalkSupported: true,
87
+ isEditorFocused: true,
83
88
  startPushToTalk: () => { },
84
89
  stopVoice: () => { stopCalls += 1; },
85
90
  });
@@ -97,6 +102,7 @@ describe("voice push-to-talk handler", () => {
97
102
  activationMode: null,
98
103
  editorText: "",
99
104
  holdToTalkSupported: false,
105
+ isEditorFocused: true,
100
106
  onUnsupported: () => { notifyCalls += 1; },
101
107
  startPushToTalk: () => { startCalls += 1; },
102
108
  stopVoice: () => { },