turbollm 1.11.1 → 1.11.6

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 (147) hide show
  1. package/README.md +23 -3
  2. package/dist/{chunk-BWZ74SDA.js → chunk-YWVYF446.js} +1 -4
  3. package/dist/cli.js +7289 -1543
  4. package/dist/{resolve-executable-ZWQDUVY3.js → resolve-executable-C5K3W6LU.js} +1 -1
  5. package/dist/webdist/assets/{AgentEditPage-D5ccnu5s.js → AgentEditPage-Dx-o_9xV.js} +1 -1
  6. package/dist/webdist/assets/{ChatScreen-BygO8zb3.js → ChatScreen-CJyYbKoe.js} +16 -16
  7. package/dist/webdist/assets/{CodeComposer-BTpMVTCA.js → CodeComposer-DxV-5HZh.js} +1 -1
  8. package/dist/webdist/assets/{CodeHomeScreen-Cz7tsGIS.js → CodeHomeScreen-CM_cnOH6.js} +1 -1
  9. package/dist/webdist/assets/{CodeSessionScreen-CFIAgEJ7.js → CodeSessionScreen-aXt0wkYo.js} +9 -9
  10. package/dist/webdist/assets/{CustomizeScreen-7zLa19h5.js → CustomizeScreen-CuzDUaab.js} +3 -3
  11. package/dist/webdist/assets/DeveloperScreen-Dxd3Z-e3.js +1 -0
  12. package/dist/webdist/assets/EnginesScreen-BhiM2yFz.js +7 -0
  13. package/dist/webdist/assets/ModelDetailDialog-BoSJpfRl.js +1 -0
  14. package/dist/webdist/assets/ModelLoadMenu-ETcY6o29.js +1 -0
  15. package/dist/webdist/assets/ModelsScreen-dgX9WkCc.js +2 -0
  16. package/dist/webdist/assets/OnboardingScreen-k7JIbQnG.js +1 -0
  17. package/dist/webdist/assets/RoutineEditPage-LfAmG_ti.js +1 -0
  18. package/dist/webdist/assets/{RoutinesPanel-DnnVr9g2.js → RoutinesPanel-BLkW0xEt.js} +1 -1
  19. package/dist/webdist/assets/SettingsScreen-_UB8piYj.js +2 -0
  20. package/dist/webdist/assets/{SidebarResizeHandle-DCZXIwhU.js → SidebarResizeHandle-D4vXg1kG.js} +1 -1
  21. package/dist/webdist/assets/{SkillEditPage-B157ySq9.js → SkillEditPage-LIPltIRO.js} +1 -1
  22. package/dist/webdist/assets/{TokensScreen-DoYPjv6Y.js → TokensScreen-TGdk-Q_d.js} +1 -1
  23. package/dist/webdist/assets/{ToolApprovalBar-ChYJChYS.js → ToolApprovalBar-DQMujhi2.js} +16 -16
  24. package/dist/webdist/assets/WorkspaceScreen-X8nfASH9.js +1 -0
  25. package/dist/webdist/assets/{abnfDiagram-N423BO3Z-YE0PLBtD.js → abnfDiagram-N423BO3Z-BYrN5G9N.js} +1 -1
  26. package/dist/webdist/assets/agent-api-LPVSxusw.js +1 -0
  27. package/dist/webdist/assets/{alert-dialog-mb66t64A.js → alert-dialog-HmXAwXqa.js} +1 -1
  28. package/dist/webdist/assets/{arc-D6tB7EyD.js → arc-ldMwjnRq.js} +1 -1
  29. package/dist/webdist/assets/{architectureDiagram-T3A2C74G-CC_g3uHG.js → architectureDiagram-T3A2C74G-BIhygyZB.js} +1 -1
  30. package/dist/webdist/assets/{arrow-left-B0kOOTXf.js → arrow-left-C8VmnG_w.js} +1 -1
  31. package/dist/webdist/assets/badge-0BCEwa1g.js +1 -0
  32. package/dist/webdist/assets/{blockDiagram-VBNYF7ZC-CDFisfPP.js → blockDiagram-VBNYF7ZC-B2kPcqcg.js} +1 -1
  33. package/dist/webdist/assets/{bot-DQc34hdo.js → bot-Brhq4CvP.js} +1 -1
  34. package/dist/webdist/assets/{c4Diagram-5PPSVZJV-Df9WlHJi.js → c4Diagram-5PPSVZJV-Bg3UFvsz.js} +1 -1
  35. package/dist/webdist/assets/channel-DxXBs2vE.js +1 -0
  36. package/dist/webdist/assets/chat-api-0uk0Mc_u.js +3 -0
  37. package/dist/webdist/assets/{chat-queries-vBDT6raC.js → chat-queries-DsoI-ftK.js} +1 -1
  38. package/dist/webdist/assets/{chevron-down-D3qQII2-.js → chevron-down-BASbdbtb.js} +1 -1
  39. package/dist/webdist/assets/{chevron-left-BQ3TyvUR.js → chevron-left-Cv4jCFYH.js} +1 -1
  40. package/dist/webdist/assets/{chevron-right-C1TzfDRc.js → chevron-right-CAxvc8lx.js} +1 -1
  41. package/dist/webdist/assets/{chunk-2GRJ4B5K--fTNBTKb.js → chunk-2GRJ4B5K-HOJ-zI2K.js} +1 -1
  42. package/dist/webdist/assets/{chunk-2Q5K7J3B-BE2H2UHk.js → chunk-2Q5K7J3B-CWYUQKvA.js} +1 -1
  43. package/dist/webdist/assets/{chunk-5RXB4S5H-C-ps6IJo.js → chunk-5RXB4S5H-C54g8FMc.js} +1 -1
  44. package/dist/webdist/assets/{chunk-5VM5RSS4-Dr6Y-wsq.js → chunk-5VM5RSS4-UEjBIEh6.js} +1 -1
  45. package/dist/webdist/assets/{chunk-6Q2QTUOP-CFP_W3le.js → chunk-6Q2QTUOP-D76HUQ1c.js} +1 -1
  46. package/dist/webdist/assets/{chunk-GF5L2VYU-eS8r3XDQ.js → chunk-GF5L2VYU-C7bGhXb0.js} +1 -1
  47. package/dist/webdist/assets/{chunk-JWPE2WC7-CnHOI6Vb.js → chunk-JWPE2WC7-CoIEx4c2.js} +1 -1
  48. package/dist/webdist/assets/{chunk-KBJHAD2P-DjKuoeJv.js → chunk-KBJHAD2P-BK5xyuR5.js} +1 -1
  49. package/dist/webdist/assets/{chunk-RYQCIY6F-BCZSATDq.js → chunk-RYQCIY6F-ItoWBj7A.js} +1 -1
  50. package/dist/webdist/assets/{chunk-XXDRQBXY-6vDQpKbX.js → chunk-XXDRQBXY-B8gm-Cx5.js} +1 -1
  51. package/dist/webdist/assets/{circle-check-CayQ1Kmr.js → circle-check-fNp1-B5t.js} +1 -1
  52. package/dist/webdist/assets/{circle-x-DBL77ehg.js → circle-x-CuhNJ5mD.js} +1 -1
  53. package/dist/webdist/assets/classDiagram-JCYQIIEL-DVemFTdO.js +1 -0
  54. package/dist/webdist/assets/classDiagram-v2-OCEON4UE-DVemFTdO.js +1 -0
  55. package/dist/webdist/assets/code-types-BuND0hhH.js +1 -0
  56. package/dist/webdist/assets/{common-COkt_JGo.js → common-DULL4Ra-.js} +1 -1
  57. package/dist/webdist/assets/{cose-bilkent-JH36ORCC-CPMWY99B.js → cose-bilkent-JH36ORCC-BKFiRS6Q.js} +1 -1
  58. package/dist/webdist/assets/{cynefin-VYW2F7L2-DCemwV3Z.js → cynefin-VYW2F7L2-Ds6Re-sx.js} +1 -1
  59. package/dist/webdist/assets/{cynefinDiagram-MW4NZA55-B8HcUCjZ.js → cynefinDiagram-MW4NZA55-BEKMr9S7.js} +1 -1
  60. package/dist/webdist/assets/{dagre-VZM6K2ZE-BC6lGXyw.js → dagre-VZM6K2ZE-Dg5dqY0j.js} +1 -1
  61. package/dist/webdist/assets/{diagram-7IWD3JNH-CQSNxirf.js → diagram-7IWD3JNH-CzaTqrpm.js} +1 -1
  62. package/dist/webdist/assets/{diagram-B4RE2ZJO-D6Ot6ZYA.js → diagram-B4RE2ZJO-_k3SLxsm.js} +1 -1
  63. package/dist/webdist/assets/{diagram-LBJQPF4R-D775f1Jb.js → diagram-LBJQPF4R-CkDl750w.js} +1 -1
  64. package/dist/webdist/assets/{diagram-Q27KOJAE-aedYX_I3.js → diagram-Q27KOJAE-BOSwNYKq.js} +1 -1
  65. package/dist/webdist/assets/{diagram-UB23O5K3-DyKXvxFs.js → diagram-UB23O5K3-BzxlhiFN.js} +1 -1
  66. package/dist/webdist/assets/{dropdown-menu-Co-9JBK7.js → dropdown-menu-gf83Mrmq.js} +1 -1
  67. package/dist/webdist/assets/{ebnfDiagram-BXEA7PRR-Dmyl6hgX.js → ebnfDiagram-BXEA7PRR-DY3DNIyj.js} +1 -1
  68. package/dist/webdist/assets/{erDiagram-JOGREHBK-DQ61Ftq2.js → erDiagram-JOGREHBK-Dfj3TSix.js} +1 -1
  69. package/dist/webdist/assets/{external-link-DeGazJd7.js → external-link-COQ5Bvdu.js} +1 -1
  70. package/dist/webdist/assets/{file-text-BqSocdvg.js → file-text-DSqIarKD.js} +1 -1
  71. package/dist/webdist/assets/{flowDiagram-UKHOOZJN-DpF0SMmj.js → flowDiagram-UKHOOZJN-BrgYXyS3.js} +1 -1
  72. package/dist/webdist/assets/{folder-input-fLAI3sbE.js → folder-input-CzY2E0mX.js} +1 -1
  73. package/dist/webdist/assets/{folder-plus-kUhRq8Qs.js → folder-plus-k0yyudVG.js} +1 -1
  74. package/dist/webdist/assets/{ganttDiagram-PKOTCBZU-C9hM2RtH.js → ganttDiagram-PKOTCBZU-cVx7lSJ0.js} +1 -1
  75. package/dist/webdist/assets/{git-branch-BLvbsQlx.js → git-branch-BZs6d67V.js} +1 -1
  76. package/dist/webdist/assets/{gitGraphDiagram-DS77QQ5N-F-m07GU8.js → gitGraphDiagram-DS77QQ5N-DL40w8Lh.js} +1 -1
  77. package/dist/webdist/assets/index-Bf0TXA7a.css +1 -0
  78. package/dist/webdist/assets/{index-Djd745uq.js → index-C6HXxZFI.js} +8 -8
  79. package/dist/webdist/assets/{infoDiagram-6WML65LV-SU_VZ3kP.js → infoDiagram-6WML65LV-BR0gJe4Y.js} +1 -1
  80. package/dist/webdist/assets/{ishikawaDiagram-WSZJBQD7-CPGrHUJl.js → ishikawaDiagram-WSZJBQD7-DsfBW9fY.js} +1 -1
  81. package/dist/webdist/assets/{journeyDiagram-NVQOT4AX-xSn5t7m_.js → journeyDiagram-NVQOT4AX-DWGKgSV9.js} +1 -1
  82. package/dist/webdist/assets/{kanban-definition-27J2QSJJ-BP6v9V-b.js → kanban-definition-27J2QSJJ-DwYsMcKD.js} +1 -1
  83. package/dist/webdist/assets/{linear-CrWjOgAX.js → linear-CVvnTc0p.js} +1 -1
  84. package/dist/webdist/assets/link-api-Dr2NcVl2.js +1 -0
  85. package/dist/webdist/assets/link-constants-CbmzSBFF.js +1 -0
  86. package/dist/webdist/assets/link-queries-CKJKivJv.js +1 -0
  87. package/dist/webdist/assets/{lock-CMnk_C6j.js → lock-Br_GtUc9.js} +1 -1
  88. package/dist/webdist/assets/{mermaid.core-Daad9FCu.js → mermaid.core-Bcb-KMMg.js} +4 -4
  89. package/dist/webdist/assets/{mindmap-definition-FAOFIHXS-BdQNGzcB.js → mindmap-definition-FAOFIHXS-B2mkpjay.js} +1 -1
  90. package/dist/webdist/assets/monitor-D2MJSfbb.js +1 -0
  91. package/dist/webdist/assets/{pegDiagram-VL7TDLO6-BVO3lisg.js → pegDiagram-VL7TDLO6-BmRtrO9J.js} +1 -1
  92. package/dist/webdist/assets/{pencil-CLqNgcwe.js → pencil-B-DJIZK4.js} +1 -1
  93. package/dist/webdist/assets/personas-UFpFvOQV.js +109 -0
  94. package/dist/webdist/assets/{pieDiagram-7S7Q4E2Y-I0avJ0HP.js → pieDiagram-7S7Q4E2Y-nc7aZNlT.js} +1 -1
  95. package/dist/webdist/assets/{plus-CZ50K8Az.js → plus-CGMFwNIS.js} +1 -1
  96. package/dist/webdist/assets/{quadrantDiagram-CIZ2JOQS-BoKPRmFq.js → quadrantDiagram-CIZ2JOQS-pKkPYA7l.js} +1 -1
  97. package/dist/webdist/assets/{railroadDiagram-AXF67PYL-nuYQFWlg.js → railroadDiagram-AXF67PYL-CAx7_Jhl.js} +1 -1
  98. package/dist/webdist/assets/{refresh-cw-ZKuYnoI-.js → refresh-cw-CSKOgioB.js} +1 -1
  99. package/dist/webdist/assets/remote-failure-B8pqD92H.js +1 -0
  100. package/dist/webdist/assets/{requirementDiagram-LRYGKXZP-BdsVsDe6.js → requirementDiagram-LRYGKXZP-DXIG1oxz.js} +1 -1
  101. package/dist/webdist/assets/{rocket-DWM7Gy7e.js → rocket-Ceqz17Tf.js} +1 -1
  102. package/dist/webdist/assets/{rotate-ccw-Dl2CDY8F.js → rotate-ccw-Cv5TSXuQ.js} +1 -1
  103. package/dist/webdist/assets/{sankeyDiagram-W5VNT64P-oCUC-z0Q.js → sankeyDiagram-W5VNT64P-DYy_y13W.js} +1 -1
  104. package/dist/webdist/assets/{sequenceDiagram-SI44F4Z6-E17XGC6k.js → sequenceDiagram-SI44F4Z6-uJNlTfiz.js} +1 -1
  105. package/dist/webdist/assets/{sizeCapture-X5ZJPWSS-B3ZZ8soS.js → sizeCapture-X5ZJPWSS-C5IPisNr.js} +1 -1
  106. package/dist/webdist/assets/{skeleton-B2R1iGLZ.js → skeleton-B6OINYhc.js} +1 -1
  107. package/dist/webdist/assets/{sliders-horizontal-S1QDbdoj.js → sliders-horizontal-CM38hmNN.js} +1 -1
  108. package/dist/webdist/assets/{sparkles-C1UduBZm.js → sparkles-Z-pONu31.js} +1 -1
  109. package/dist/webdist/assets/{star-6fg60gkG.js → star-DMVePf7b.js} +1 -1
  110. package/dist/webdist/assets/{stateDiagram-OKZ733FA-uJ7BcjMS.js → stateDiagram-OKZ733FA-Da9REfgi.js} +1 -1
  111. package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-CxJUIzH9.js +1 -0
  112. package/dist/webdist/assets/{swimlanes-SLNWSIFB-C5Rg25iw.js → swimlanes-SLNWSIFB-DdoEQTQk.js} +2 -2
  113. package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-CstzYf1d.js +8 -0
  114. package/dist/webdist/assets/{switch-_T-NWlJj.js → switch-DPFLAHpN.js} +1 -1
  115. package/dist/webdist/assets/{terminal-jZn2njs8.js → terminal-DFhvh4k1.js} +1 -1
  116. package/dist/webdist/assets/{timeline-definition-Z64GVDOM-DCgYtPRm.js → timeline-definition-Z64GVDOM-D2oRIsdl.js} +1 -1
  117. package/dist/webdist/assets/{trash-2-C5UxcfNn.js → trash-2-D1G8EUUf.js} +1 -1
  118. package/dist/webdist/assets/{triangle-alert-BLYFYhrL.js → triangle-alert-ChRtySvU.js} +1 -1
  119. package/dist/webdist/assets/{useIsDesktop-Db8d_FwF.js → useIsDesktop-BAU4oGSf.js} +1 -1
  120. package/dist/webdist/assets/{vennDiagram-T6HMQDX7-Bu0txarq.js → vennDiagram-T6HMQDX7-tDiJA0Ny.js} +1 -1
  121. package/dist/webdist/assets/vram-Bc_Twhr0.js +1 -0
  122. package/dist/webdist/assets/{wardleyDiagram-T6FBY63Y-LfdOSJGM.js → wardleyDiagram-T6FBY63Y-CM3_MwtW.js} +1 -1
  123. package/dist/webdist/assets/{wrench-R5NYyfgk.js → wrench-CTkAByRe.js} +1 -1
  124. package/dist/webdist/assets/{xychartDiagram-ELKLHX3M-CQSLgZgd.js → xychartDiagram-ELKLHX3M-BbPp91bK.js} +1 -1
  125. package/dist/webdist/index.html +2 -2
  126. package/package.json +1 -1
  127. package/dist/webdist/assets/DeveloperScreen-e8_tLsWt.js +0 -1
  128. package/dist/webdist/assets/EnginesScreen-hn6IM67U.js +0 -7
  129. package/dist/webdist/assets/ModelDetailDialog-DN-kl63r.js +0 -1
  130. package/dist/webdist/assets/ModelLoadMenu-Dgy2n0qW.js +0 -1
  131. package/dist/webdist/assets/ModelsScreen-COQU83v_.js +0 -2
  132. package/dist/webdist/assets/OnboardingScreen-BcjUSBAv.js +0 -1
  133. package/dist/webdist/assets/RoutineEditPage-BtYITioy.js +0 -1
  134. package/dist/webdist/assets/SettingsScreen-0NoDCta7.js +0 -2
  135. package/dist/webdist/assets/WorkspaceScreen-BrA4DSov.js +0 -1
  136. package/dist/webdist/assets/agent-api-DyPUCnyd.js +0 -1
  137. package/dist/webdist/assets/badge-BaPl3cu1.js +0 -1
  138. package/dist/webdist/assets/channel-rIJvIL9_.js +0 -1
  139. package/dist/webdist/assets/chat-api-B7cm_Kjj.js +0 -3
  140. package/dist/webdist/assets/classDiagram-JCYQIIEL-CKHNwlA2.js +0 -1
  141. package/dist/webdist/assets/classDiagram-v2-OCEON4UE-CKHNwlA2.js +0 -1
  142. package/dist/webdist/assets/code-types-jzTJE-lB.js +0 -1
  143. package/dist/webdist/assets/index-yZ-DNSjl.css +0 -1
  144. package/dist/webdist/assets/personas-Bdrl3tL6.js +0 -390
  145. package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-C03mcgmI.js +0 -1
  146. package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-Cnm-o6w8.js +0 -8
  147. package/dist/webdist/assets/vram-BW-GKnZ2.js +0 -1
package/README.md CHANGED
@@ -291,6 +291,13 @@ the detail:
291
291
  in chat (name, preferences, hardware) using your own loaded model, and carries them into future
292
292
  new conversations. Nothing leaves your device; the full fact list is reviewable and deletable
293
293
  from Settings → Memory, and turning the toggle off stops new chats from seeing it immediately.
294
+ - **Turbo Link** *(experimental, off by default)* — link a second machine running TurboLLM
295
+ with one pasted link string and use its models as if they were local: they appear in the chat
296
+ model picker (grouped by machine), in `/v1/models` and in `launch --model`, and Models,
297
+ Downloads and Engines merge both machines' rows into one list. You grant an explicit capability
298
+ set per link — use models only, run a server, or full control — optionally pinned to specific
299
+ models, and revocable at any time from the host. Not yet verified against a real two-machine
300
+ setup, so it stays behind Settings → Experimental.
294
301
  - **Thinking-budget control** — a graduated slider, not just on/off: cap reasoning to a specific
295
302
  token count, disable it entirely, or leave it unlimited. Works in Chat and Code alike.
296
303
  - **Reasoning-effort control** for models whose own chat template supports it (e.g. Qwen3.8) —
@@ -326,10 +333,12 @@ there. Entirely local; nothing leaves your machine.
326
333
  MCP-compatible tool (Claude Desktop, Cursor, Windsurf, Cline, Claude Code, and more) can
327
334
  delegate a real coding task to Code, not just chat completions. Setup snippets for any host are
328
335
  in the Developer tab.
329
- - **Or run Claude Code itself, inside Code** — set Settings → Code agent to `claude` and a session
336
+ - **Or run Claude Code, `pi` or `opencode` itself, inside Code** — set Settings → Code agent and a session
330
337
  opens the real CLI in a full-screen terminal, on your local model, in your project folder. The
331
338
  model picker, context ring, thinking-budget slider and stats row stay right where they are: the
332
- CLI replaces the transcript, not the controls. It starts in the mode you picked (auto / plan /
339
+ CLI replaces the transcript, not the controls. Any of the three not installed yet is shown
340
+ with an Install button rather than failing when you open the session, and a CLI launched this
341
+ way sees only your local models — never your cloud API keys. It starts in the mode you picked (auto / plan /
333
342
  ask), the thinking budget applies live with no restart, switching models keeps your scrollback,
334
343
  and the conversation survives a restart of TurboLLM. The terminal backend is an optional native
335
344
  component — if it can't be built for your platform it's skipped (TurboLLM installs and runs
@@ -353,7 +362,7 @@ there. Entirely local; nothing leaves your machine.
353
362
  </details>
354
363
 
355
364
  <details>
356
- <summary><strong>🔌 APIs &amp; integrations — OpenAI + Anthropic, plus a model-loading gateway</strong></summary>
365
+ <summary><strong>🔌 APIs &amp; integrations — OpenAI + Anthropic, a model-loading gateway, and a stateful chat API</strong></summary>
357
366
 
358
367
  <br/>
359
368
 
@@ -373,6 +382,17 @@ curl http://127.0.0.1:6996/v1/chat/completions \
373
382
  Claude Code below. No other local host offers this.
374
383
  - **Structured output** — constrain any response to a **GBNF grammar** (or JSON shape).
375
384
  - **API-key auth** you can require when sharing over a LAN (Settings → Network & sharing).
385
+ - **A stateful External Chat API** (**Experimental — manual setup, no onboarding UI yet**),
386
+ `/api/ext/v1`, for building a real chat product instead of the gateway's stateless
387
+ send-full-history-every-call model — persistence, history, message editing, and resumable
388
+ streaming generation are handled for you. Off by default; using it today needs two manual
389
+ `config.json` edits — a key with an explicit, non-`local` `tenant` field (the local tenant, this
390
+ install's own desktop UI data, is never reachable through this API), and a configured
391
+ `chatStore` adapter (the SQLite default only ever serves the `local` tenant). A generated
392
+ OpenAPI spec, a TypeScript client, and a working Postgres adapter example ship with it. The
393
+ daemon logs a warning at startup while it's enabled — a remote tenant's generations currently
394
+ inherit this install's own tool permissions, not an independent trust boundary of their own.
395
+ [Full guide](https://turbollm.dev/docs/api/external).
376
396
 
377
397
  **The gateway loads models for you.** Most local hosts make you load a model first, then call it.
378
398
  TurboLLM's gateway reads the `model` field of any incoming request, **fuzzy-matches it to your
@@ -25,10 +25,7 @@ function resolveExecutable(command, env = process.env, platform = process.platfo
25
25
  if (!command) return null;
26
26
  const win32 = platform === "win32";
27
27
  const exts = win32 ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean).map((e) => e.toLowerCase()) : [""];
28
- const candidates = (base) => (
29
- // An explicit extension is honoured as-is; only an extension-less command gets PATHEXT applied.
30
- extname(base) ? [base] : [base, ...exts.map((e) => base + e)]
31
- );
28
+ const candidates = (base) => extname(base) ? [base] : win32 ? exts.map((e) => base + e) : [base];
32
29
  if (isAbsolute(command) || command.startsWith("./") || command.startsWith(".\\")) {
33
30
  return candidates(command).find(isExecutableFile) ?? null;
34
31
  }