@ashx-j/lunr 0.2.14 → 0.2.16

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 (215) hide show
  1. package/CHANGELOG.md +24 -1
  2. package/README.md +4 -4
  3. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  4. package/dist/builtin-extensions/ashxj-tui.js +4 -4
  5. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  6. package/dist/builtin-extensions/index.d.ts.map +1 -1
  7. package/dist/builtin-extensions/index.js +2 -0
  8. package/dist/builtin-extensions/index.js.map +1 -1
  9. package/dist/builtin-extensions/lunr-settings-tools.d.ts +4 -0
  10. package/dist/builtin-extensions/lunr-settings-tools.d.ts.map +1 -0
  11. package/dist/builtin-extensions/lunr-settings-tools.js +120 -0
  12. package/dist/builtin-extensions/lunr-settings-tools.js.map +1 -0
  13. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.d.ts.map +1 -1
  14. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js +6 -2
  15. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js.map +1 -1
  16. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.d.ts +2 -2
  17. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.js.map +1 -1
  19. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.d.ts.map +1 -1
  20. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.js +3 -3
  21. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.js.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/api/delegation.d.ts +2 -2
  23. package/dist/builtin-extensions/pi-subagents/src/api/delegation.d.ts.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/api/delegation.js +1 -1
  25. package/dist/builtin-extensions/pi-subagents/src/api/delegation.js.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  27. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +2 -1
  28. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  29. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +5 -11
  30. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  31. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +12 -15
  32. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  33. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +3 -3
  34. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  35. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +14 -27
  36. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  37. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  38. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +6 -4
  39. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  40. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
  41. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +2 -1
  42. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
  43. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
  44. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +6 -4
  45. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
  46. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.d.ts.map +1 -1
  47. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js +4 -2
  48. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js.map +1 -1
  49. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.d.ts.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js +3 -35
  51. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js.map +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +5 -12
  54. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  56. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +14 -31
  57. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  58. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +2 -0
  59. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +28 -22
  61. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
  63. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  65. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
  66. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +9 -4
  67. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
  68. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +1 -1
  69. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
  70. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +2 -2
  71. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
  72. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +4 -7
  73. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  74. package/dist/builtin-extensions/pi-subagents/src/shared/types.js +1 -1
  75. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  76. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts +3 -3
  77. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
  78. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js +7 -6
  79. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
  80. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.d.ts.map +1 -1
  81. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.js +3 -3
  82. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.js.map +1 -1
  83. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +1 -1
  84. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  85. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +6 -4
  86. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  87. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +1 -1
  88. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  89. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +15 -10
  90. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  91. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.d.ts.map +1 -1
  92. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js +3 -2
  93. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js.map +1 -1
  94. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -2
  95. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  96. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +75 -43
  97. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  98. package/dist/core/agent-session-runtime.d.ts +5 -1
  99. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  100. package/dist/core/agent-session-runtime.js +7 -2
  101. package/dist/core/agent-session-runtime.js.map +1 -1
  102. package/dist/core/agent-session.d.ts +5 -0
  103. package/dist/core/agent-session.d.ts.map +1 -1
  104. package/dist/core/agent-session.js +68 -10
  105. package/dist/core/agent-session.js.map +1 -1
  106. package/dist/core/compaction/compaction.d.ts.map +1 -1
  107. package/dist/core/compaction/compaction.js +10 -5
  108. package/dist/core/compaction/compaction.js.map +1 -1
  109. package/dist/core/context-breakdown.d.ts +2 -0
  110. package/dist/core/context-breakdown.d.ts.map +1 -1
  111. package/dist/core/context-breakdown.js +6 -2
  112. package/dist/core/context-breakdown.js.map +1 -1
  113. package/dist/core/extensions/types.d.ts +2 -2
  114. package/dist/core/extensions/types.d.ts.map +1 -1
  115. package/dist/core/extensions/types.js.map +1 -1
  116. package/dist/core/injected-prompt.d.ts +3 -3
  117. package/dist/core/injected-prompt.d.ts.map +1 -1
  118. package/dist/core/injected-prompt.js +2 -7
  119. package/dist/core/injected-prompt.js.map +1 -1
  120. package/dist/core/large-subagent-launch.d.ts +13 -0
  121. package/dist/core/large-subagent-launch.d.ts.map +1 -0
  122. package/dist/core/large-subagent-launch.js +54 -0
  123. package/dist/core/large-subagent-launch.js.map +1 -0
  124. package/dist/core/model-instructions.d.ts +24 -0
  125. package/dist/core/model-instructions.d.ts.map +1 -0
  126. package/dist/core/model-instructions.js +123 -0
  127. package/dist/core/model-instructions.js.map +1 -0
  128. package/dist/core/permissions.d.ts +10 -11
  129. package/dist/core/permissions.d.ts.map +1 -1
  130. package/dist/core/permissions.js +107 -40
  131. package/dist/core/permissions.js.map +1 -1
  132. package/dist/core/plan-mode.d.ts.map +1 -1
  133. package/dist/core/plan-mode.js +10 -1
  134. package/dist/core/plan-mode.js.map +1 -1
  135. package/dist/core/resource-loader.d.ts +3 -0
  136. package/dist/core/resource-loader.d.ts.map +1 -1
  137. package/dist/core/resource-loader.js +13 -4
  138. package/dist/core/resource-loader.js.map +1 -1
  139. package/dist/core/runtime-bridges.d.ts +4 -0
  140. package/dist/core/runtime-bridges.d.ts.map +1 -0
  141. package/dist/core/runtime-bridges.js +16 -0
  142. package/dist/core/runtime-bridges.js.map +1 -0
  143. package/dist/core/sdk.d.ts.map +1 -1
  144. package/dist/core/sdk.js +1 -0
  145. package/dist/core/sdk.js.map +1 -1
  146. package/dist/core/settings-manager.d.ts +13 -0
  147. package/dist/core/settings-manager.d.ts.map +1 -1
  148. package/dist/core/settings-manager.js +32 -0
  149. package/dist/core/settings-manager.js.map +1 -1
  150. package/dist/core/settings-tools-bridge.d.ts +35 -0
  151. package/dist/core/settings-tools-bridge.d.ts.map +1 -0
  152. package/dist/core/settings-tools-bridge.js +56 -0
  153. package/dist/core/settings-tools-bridge.js.map +1 -0
  154. package/dist/core/slash-commands.d.ts.map +1 -1
  155. package/dist/core/slash-commands.js +0 -1
  156. package/dist/core/slash-commands.js.map +1 -1
  157. package/dist/core/system-prompt.d.ts.map +1 -1
  158. package/dist/core/system-prompt.js +1 -1
  159. package/dist/core/system-prompt.js.map +1 -1
  160. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  161. package/dist/gateway/agent-bridge.js +3 -2
  162. package/dist/gateway/agent-bridge.js.map +1 -1
  163. package/dist/gateway/approval.d.ts.map +1 -1
  164. package/dist/gateway/approval.js +4 -3
  165. package/dist/gateway/approval.js.map +1 -1
  166. package/dist/gateway/commands.d.ts +1 -1
  167. package/dist/gateway/commands.d.ts.map +1 -1
  168. package/dist/gateway/commands.js +1 -18
  169. package/dist/gateway/commands.js.map +1 -1
  170. package/dist/gateway/cron.d.ts.map +1 -1
  171. package/dist/gateway/cron.js +3 -2
  172. package/dist/gateway/cron.js.map +1 -1
  173. package/dist/gateway/router.d.ts +1 -1
  174. package/dist/gateway/router.d.ts.map +1 -1
  175. package/dist/gateway/router.js +1 -1
  176. package/dist/gateway/router.js.map +1 -1
  177. package/dist/main.d.ts.map +1 -1
  178. package/dist/main.js +3 -9
  179. package/dist/main.js.map +1 -1
  180. package/dist/migrations.d.ts.map +1 -1
  181. package/dist/migrations.js +4 -0
  182. package/dist/migrations.js.map +1 -1
  183. package/dist/modes/interactive/components/injected-prompt-message.d.ts +1 -1
  184. package/dist/modes/interactive/components/injected-prompt-message.d.ts.map +1 -1
  185. package/dist/modes/interactive/components/injected-prompt-message.js +1 -1
  186. package/dist/modes/interactive/components/injected-prompt-message.js.map +1 -1
  187. package/dist/modes/interactive/components/settings-selector.d.ts +8 -1
  188. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  189. package/dist/modes/interactive/components/settings-selector.js +61 -1
  190. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  191. package/dist/modes/interactive/interactive-mode.d.ts +3 -3
  192. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  193. package/dist/modes/interactive/interactive-mode.js +45 -54
  194. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  195. package/docs/compaction.md +5 -3
  196. package/docs/features.md +7 -7
  197. package/docs/quickstart.md +2 -1
  198. package/docs/settings.md +3 -1
  199. package/docs/termux.md +1 -1
  200. package/docs/usage.md +2 -2
  201. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  202. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  203. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  204. package/examples/extensions/gondolin/package-lock.json +2 -2
  205. package/examples/extensions/gondolin/package.json +1 -1
  206. package/examples/extensions/sandbox/package-lock.json +2 -2
  207. package/examples/extensions/sandbox/package.json +1 -1
  208. package/examples/extensions/subagent/README.md +1 -1
  209. package/examples/extensions/with-deps/package-lock.json +2 -2
  210. package/examples/extensions/with-deps/package.json +1 -1
  211. package/package.json +4 -4
  212. package/dist/core/swarm.d.ts +0 -54
  213. package/dist/core/swarm.d.ts.map +0 -1
  214. package/dist/core/swarm.js +0 -119
  215. package/dist/core/swarm.js.map +0 -1
@@ -34,7 +34,9 @@ contextTokens > contextWindow - reserveTokens
34
34
 
35
35
  By default, `reserveTokens` is 16384 tokens (configurable in `~/.lunr/agent/settings.json` or `<project-dir>/.lunr/settings.json`). This leaves room for the LLM's response.
36
36
 
37
- You can also trigger manually with `/compact [instructions]`, where optional instructions focus the summary.
37
+ For Codex OAuth models, lunR checks the threshold after each complete batch of tool results. If the batch crosses the threshold, lunR compacts before sending the next provider request.
38
+
39
+ You can also trigger manually with `/compact [instructions]`, where optional instructions focus the summary. Running `/compact` again at an unchanged compaction boundary is a no-op.
38
40
 
39
41
  ### How It Works
40
42
 
@@ -114,7 +116,7 @@ Valid cut points are:
114
116
  - BashExecution messages
115
117
  - Custom messages (custom_message, branch_summary)
116
118
 
117
- Never cut at tool results (they must stay with their tool call).
119
+ Never cut at tool results (they must stay with their tool call). If the recent-token budget lands on a tool result, lunR keeps the assistant message containing its tool call.
118
120
 
119
121
  ### CompactionEntry Structure
120
122
 
@@ -288,7 +290,7 @@ pi.on("session_before_compact", async (event, ctx) => {
288
290
 
289
291
  // branchEntries - all entries on current branch (for custom state)
290
292
  // reason - "manual" (/compact), "threshold", or "overflow"
291
- // willRetry - whether the aborted turn is retried after compaction (overflow recovery)
293
+ // willRetry - whether the active run sends another provider request after compaction
292
294
  // signal - AbortSignal (pass to LLM calls)
293
295
 
294
296
  // Cancel:
package/docs/features.md CHANGED
@@ -9,7 +9,7 @@ Sample code under `examples/extensions/plan-mode`, `examples/extensions/todo.ts`
9
9
  Permission modes: `manual | yolo | plan | auto`. Shift+Tab (`app.mode.cycle`) cycles that order. Thinking cycle is unbound; use `/thinking`, `/effort`, or `/reasoning`.
10
10
 
11
11
  - **manual** — approve every tool
12
- - **yolo** — auto-approve tools; **does not** bypass the swarm gate
12
+ - **yolo** — auto-approve ordinary tools; large subagent launches still request confirmation
13
13
  - **plan** — read-oriented planning; the model calls `present_plan` with a summary; you approve or decline in a dock
14
14
  - **auto** — fully autonomous
15
15
 
@@ -17,13 +17,11 @@ Permission modes: `manual | yolo | plan | auto`. Shift+Tab (`app.mode.cycle`) cy
17
17
 
18
18
  `present_plan` is only available in plan mode. After approval, interactive lunR leaves plan mode before the tool result resolves.
19
19
 
20
- ## Subagents and swarm
20
+ ## Subagents
21
21
 
22
22
  Advertised subagents always start **fresh** (no forked parent context). Default parallel concurrency / max tasks / global run cap are unlimited; an explicit `concurrency` is still honored.
23
23
 
24
- A **swarm** is 3+ parallel subagents in one `tasks`/`chain.parallel` call, or 3+ same-turn SINGLE `subagent` calls. Swarms are gated in **manual and yolo**. Sequential work stays `chain`.
25
-
26
- - `/swarm <task>` — orchestrate parallel subagents
24
+ A launch of 3+ parallel children in one `tasks`/`chain.parallel` call, or 3+ same-turn SINGLE `subagent` calls, receives one aggregate confirmation in **manual and yolo**. Sequential work stays `chain`. Auto bypasses this confirmation, and it can be disabled independently in `/settings`.
27
25
 
28
26
  `/goal` sets a session goal and **forces session auto** permission mode.
29
27
 
@@ -31,7 +29,8 @@ A **swarm** is 3+ parallel subagents in one `tasks`/`chain.parallel` call, or 3+
31
29
 
32
30
  - **Todos** — lunr-todos is a full-replace list. Completed todos prune on the next user turn (no leftover `✓ N done` footer).
33
31
  - **Agent memory** — durable established facts and stable preferences in `~/.lunr/simple-memory/memory.md`. `/settings` → Agent memory controls injection and the `memory_add`, `memory_remove`, and `memory_load` tools without deleting stored facts. `memoryCharCap` defaults to 5000. Behavior instructions, transient task state, transcripts, guesses, and secrets do not belong in memory.
34
- - **Global instructions** — create `~/.lunr/agent/AGENTS.md` yourself when you want global behavior or instructions. lunR injects it through the normal context loader; `/reload` picks up changes. The model cannot modify this user-managed file. The retired `behavior.md` file and behavior presets are no longer loaded.
32
+ - **Global instructions** — create `~/.lunr/agent/agents/AGENTS.md` yourself when you want global behavior or instructions. lunR injects it through the normal context loader; `/reload` picks up changes. The model cannot modify this user-managed file. The retired `behavior.md` file and behavior presets are no longer loaded.
33
+ - **Model instructions** — `/settings` can enable `~/.lunr/agent/agents/<model-name>/AGENTS.md` and choose **Both** (global then model-specific) or **Model only**. The folder name is provider-independent and filesystem-safe. Project `AGENTS.md`/`CLAUDE.md` files are unaffected, and `--no-context-files` disables all instruction files.
35
34
 
36
35
  ## Cron
37
36
 
@@ -86,7 +85,8 @@ Without runnable adapters (enabled platform + resolvable token), `lunr gateway`
86
85
  - Click a ✻ Thought or tool card to expand/collapse that item. `app.tools.expand` is unbound. `/tree` still uses `ctrl+o` for filters.
87
86
  - Smooth streaming (`smoothStreaming`, default off) is **interactive TUI only** (grapheme reveal at ~30 FPS). Print, RPC, and gateway stay unsmoothed.
88
87
  - Image paste inserts `[image_n]` chips. Windows uses **Alt+V**; VS Code must forward it because it owns Ctrl+V and Alt+V. `/paste-image` bypasses terminal shortcuts.
89
- - Model tiers: `/settings` Enable model tiers. Per-tier thinking; unset = parent session.
88
+ - Model tiers: every child launch selects `light`, `standard`, or `heavy`. Configure authenticated models for those routes in `/settings`; a missing, disabled, unauthenticated, or unavailable route fails closed. Per-tier thinking is optional; unset inherits the parent session.
89
+ - Settings tools: `settings_load` is always available to the model. It injects four narrowly scoped tools for model tiers, model instruction subscriptions, rollback behavior, and session retention only after the model requests them.
90
90
 
91
91
  ## Updates, catalogs, local models
92
92
 
@@ -121,7 +121,8 @@ lunR loads context files at startup. Add an `AGENTS.md` file to tell it how to w
121
121
 
122
122
  lunR loads:
123
123
 
124
- - `~/.lunr/agent/AGENTS.md` for global instructions
124
+ - `~/.lunr/agent/agents/AGENTS.md` for global instructions
125
+ - `~/.lunr/agent/agents/<model-name>/AGENTS.md` for optional model-specific instructions enabled in `/settings`
125
126
  - `AGENTS.md` or `CLAUDE.md` from parent directories and the current directory
126
127
 
127
128
  Restart lunR, or run `/reload`, after changing context files.
package/docs/settings.md CHANGED
@@ -64,6 +64,8 @@ Use `/trust` in interactive mode to save a project trust decision for future ses
64
64
  | `memoryCharCap` | number | `5000` | Durable-facts memory character cap (1–30000) |
65
65
  | `sessionRetentionDays` | number | `30` | Delete session files older than N days at launch; `0` keeps forever |
66
66
  | `modelTiers` | object | - | Enable model tiers and per-tier thinking |
67
+ | `modelInstructions` | object | `{ enabled: false, mode: "both" }` | Model-specific instructions and whether they append to or replace global instructions |
68
+ | `confirmLargeSubagentLaunches` | boolean | `true` | Ask once before aggregate launches of three or more children outside Auto mode |
67
69
  | `enableAnalytics` | boolean | `false` | Opt-in analytics data sharing. Currently only asked for during the experimental first-time setup (`PI_EXPERIMENTAL=1`) |
68
70
  | `trackingId` | string | - | Analytics tracking identifier, generated when `enableAnalytics` is turned on |
69
71
  | `doubleEscapeAction` | string | `"tree"` | Action for double-escape: `"tree"`, `"fork"`, or `"none"` |
@@ -230,7 +232,7 @@ When multiple sources specify a session directory, precedence is `--session-dir`
230
232
  | `footerTokens` | boolean | `true` | Show ↑in ↓out token totals |
231
233
  | `footerCacheHitRate` | boolean | `true` | Show the latest prompt cache-hit rate when reported |
232
234
  | `footerTps` | boolean | `true` | Show tokens/second. Independent of feature statuses |
233
- | `footerStatuses` | boolean | `true` | Show plan/goal/swarm status segments |
235
+ | `footerStatuses` | boolean | `true` | Show plan and goal status segments |
234
236
  | `footerGit` | boolean | `true` | Show git branch + added/removed |
235
237
  | `footerPlan` | boolean | `true` | Show the subscription usage segment |
236
238
  | `footerPlanBar` | boolean | `true` | Show the █░ fill; off keeps the percent only |
package/docs/termux.md CHANGED
@@ -34,7 +34,7 @@ Image clipboard is not supported on Termux (the `ctrl+v` image paste feature wil
34
34
 
35
35
  ## Example AGENTS.md for Termux
36
36
 
37
- Create `~/.lunr/agent/AGENTS.md` to help the agent understand the Termux environment:
37
+ Create `~/.lunr/agent/agents/AGENTS.md` to help the agent understand the Termux environment:
38
38
 
39
39
  ````markdown
40
40
  # Agent Environment: Termux on Android
package/docs/usage.md CHANGED
@@ -69,7 +69,6 @@ Built-in commands (from `slash-commands.ts`):
69
69
  | `/logout`, `/deauth` | Remove provider authentication |
70
70
  | `/new` | Start a new session |
71
71
  | `/init` | Generate a starter AGENTS.md for this project |
72
- | `/swarm` | Orchestrate parallel subagents for a complex task |
73
72
  | `/compact` | Manually compact the session context |
74
73
  | `/resume`, `/sessions` | Browse and resume sessions |
75
74
  | `/reload` | Reload keybindings, extensions, skills, prompts, themes, and context files |
@@ -121,7 +120,8 @@ See [Sessions](sessions.md) and [Compaction](compaction.md) for details.
121
120
 
122
121
  lunR loads `AGENTS.md` or `CLAUDE.md` at startup from:
123
122
 
124
- - `~/.lunr/agent/AGENTS.md` for global instructions
123
+ - `~/.lunr/agent/agents/AGENTS.md` for global instructions
124
+ - `~/.lunr/agent/agents/<model-name>/AGENTS.md` for optional model-specific instructions enabled in `/settings`
125
125
  - parent directories, walking up from the current working directory
126
126
  - the current directory
127
127
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "0.2.14",
9
+ "version": "0.2.16",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "0.2.14",
4
+ "version": "0.2.16",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "0.2.14",
4
+ "version": "0.2.16",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-gondolin",
9
- "version": "0.2.14",
9
+ "version": "0.2.16",
10
10
  "dependencies": {
11
11
  "@earendil-works/gondolin": "0.12.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
3
  "private": true,
4
- "version": "0.2.14",
4
+ "version": "0.2.16",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-sandbox",
9
- "version": "0.2.14",
9
+ "version": "0.2.16",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sandbox-runtime": "^0.0.26"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
3
  "private": true,
4
- "version": "0.2.14",
4
+ "version": "0.2.16",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,6 +1,6 @@
1
1
  # Subagent Example (sample)
2
2
 
3
- This is an **Extension API sample**, not lunR's product subagent implementation. lunR ships baked-in subagents (always fresh; swarm gate for 3+ parallel). See [docs/features.md](../../../docs/features.md).
3
+ This is an **Extension API sample**, not lunR's product subagent implementation. lunR ships baked-in subagents (always fresh; aggregate confirmation for 3+ parallel). See [docs/features.md](../../../docs/features.md).
4
4
 
5
5
  Delegate tasks to specialized subagents with isolated context windows.
6
6
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "0.2.14",
9
+ "version": "0.2.16",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
3
  "private": true,
4
- "version": "0.2.14",
4
+ "version": "0.2.16",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ashx-j/lunr",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "description": "lunR — terminal coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -37,9 +37,9 @@
37
37
  "shrinkwrap": "node ../../scripts/generate-coding-agent-shrinkwrap.mjs"
38
38
  },
39
39
  "dependencies": {
40
- "@ashx-j/lunr-agent": "^0.2.14",
41
- "@ashx-j/lunr-ai": "^0.2.14",
42
- "@ashx-j/lunr-tui": "^0.2.14",
40
+ "@ashx-j/lunr-agent": "^0.2.16",
41
+ "@ashx-j/lunr-ai": "^0.2.16",
42
+ "@ashx-j/lunr-tui": "^0.2.16",
43
43
  "@modelcontextprotocol/ext-apps": "1.7.4",
44
44
  "@modelcontextprotocol/sdk": "1.30.0",
45
45
  "@mozilla/readability": "0.6.0",
@@ -1,54 +0,0 @@
1
- /**
2
- * lunR: reusable swarm prompt builder.
3
- *
4
- * Moved out of interactive-mode so the gateway can decompose tasks across
5
- * parallel subagents the same way the TUI does.
6
- */
7
- export declare function buildSwarmPrompt(task: string): string;
8
- /**
9
- * lunR: agent-swarm auto-activation gate helpers.
10
- *
11
- * When the model launches more than SWARM_APPROVAL_THRESHOLD parallel subagents
12
- * in one `subagent` `tasks`/`chain.parallel` call, or that many same-turn SINGLE
13
- * `subagent` calls, that counts as an auto-activated agent swarm and requires
14
- * user approval in every permission mode except `auto` (see core/permissions.ts).
15
- * An explicit /swarm turn is pre-approved because the user already asked for the swarm.
16
- */
17
- /** Parallel-subagent count above which the swarm approval gate engages. */
18
- export declare const SWARM_APPROVAL_THRESHOLD = 2;
19
- /**
20
- * Effective number of parallel subagents a `subagent` tool call will launch:
21
- * the `tasks` array (with `count` multipliers) plus any `chain` step `parallel`
22
- * fan-out blocks. Sequential chain steps and single-agent calls count as 0.
23
- * Dynamic `expand` fan-out has no static count and is not gated.
24
- */
25
- export declare function effectiveSwarmCount(args: Record<string, unknown>): number;
26
- interface AssistantMessageLike {
27
- content?: ReadonlyArray<{
28
- type?: string;
29
- name?: string;
30
- arguments?: unknown;
31
- }>;
32
- }
33
- /**
34
- * Parallel subagent count for the swarm gate. Uses this call's `tasks` / chain
35
- * `parallel` blocks, plus every other same-turn SINGLE `subagent` call so three
36
- * sibling singles still trip the >2 approval gate.
37
- */
38
- export declare function effectiveSwarmCountForTurn(args: Record<string, unknown>, assistantMessage?: AssistantMessageLike): number;
39
- interface BranchEntryLike {
40
- type: string;
41
- message?: {
42
- role?: string;
43
- content?: unknown;
44
- };
45
- }
46
- /**
47
- * True when the current turn started from an explicit /swarm prompt (the most
48
- * recent user message carries the literal `[SWARM MODE]` prefix). Both the TUI
49
- * and the gateway inject the same buildSwarmPrompt text, so this works on both
50
- * surfaces without extra state.
51
- */
52
- export declare function isExplicitSwarmTurn(branch: readonly BranchEntryLike[]): boolean;
53
- export {};
54
- //# sourceMappingURL=swarm.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../../src/core/swarm.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUrD;AAED;;;;;;;;GAQG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAe1C;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAczE;AAaD,UAAU,oBAAoB;IAC7B,OAAO,CAAC,EAAE,aAAa,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC/E;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,gBAAgB,CAAC,EAAE,oBAAoB,GACrC,MAAM,CAYR;AAED,UAAU,eAAe;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC/C;AAaD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,OAAO,CAO/E","sourcesContent":["/**\n * lunR: reusable swarm prompt builder.\n *\n * Moved out of interactive-mode so the gateway can decompose tasks across\n * parallel subagents the same way the TUI does.\n */\n\nexport function buildSwarmPrompt(task: string): string {\n\treturn `[SWARM MODE] Task: ${task}\nAct as an orchestrator. 1) Decompose into 3-8 independent subtasks. 2) Launch them\nin ONE parallel subagent call (async:false) as generic children, each with task,\ndescription, and permissions (\"full\" or \"read-only\"; omit permissions for full).\nUse read-only children for inspection/review and full children only when edits\nare required. Pick a model tier per subtask. 3) Synthesize the results and report.\nRules: max 8 concurrent children; no nested fan-out; if a subtask fails, retry\nonce with the heavy tier before giving up on it; keep your final report under\n100 lines with per-subtask status.`;\n}\n\n/**\n * lunR: agent-swarm auto-activation gate helpers.\n *\n * When the model launches more than SWARM_APPROVAL_THRESHOLD parallel subagents\n * in one `subagent` `tasks`/`chain.parallel` call, or that many same-turn SINGLE\n * `subagent` calls, that counts as an auto-activated agent swarm and requires\n * user approval in every permission mode except `auto` (see core/permissions.ts).\n * An explicit /swarm turn is pre-approved because the user already asked for the swarm.\n */\n\n/** Parallel-subagent count above which the swarm approval gate engages. */\nexport const SWARM_APPROVAL_THRESHOLD = 2;\n\nfunction countEntry(item: unknown): number {\n\tconst count = item && typeof item === \"object\" ? (item as { count?: unknown }).count : undefined;\n\treturn typeof count === \"number\" && Number.isInteger(count) && count >= 1 ? count : 1;\n}\n\nfunction isManagementCall(args: Record<string, unknown>): boolean {\n\treturn typeof args.action === \"string\" && args.action.length > 0;\n}\n\nfunction isAsyncDetached(args: Record<string, unknown>): boolean {\n\treturn args.async === true && args.clarify !== true;\n}\n\n/**\n * Effective number of parallel subagents a `subagent` tool call will launch:\n * the `tasks` array (with `count` multipliers) plus any `chain` step `parallel`\n * fan-out blocks. Sequential chain steps and single-agent calls count as 0.\n * Dynamic `expand` fan-out has no static count and is not gated.\n */\nexport function effectiveSwarmCount(args: Record<string, unknown>): number {\n\tlet total = 0;\n\tif (Array.isArray(args.tasks)) {\n\t\tfor (const task of args.tasks) total += countEntry(task);\n\t}\n\tif (Array.isArray(args.chain)) {\n\t\tfor (const step of args.chain) {\n\t\t\tconst parallel = step && typeof step === \"object\" ? (step as { parallel?: unknown }).parallel : undefined;\n\t\t\tif (Array.isArray(parallel)) {\n\t\t\t\tfor (const child of parallel) total += countEntry(child);\n\t\t\t}\n\t\t}\n\t}\n\treturn total;\n}\n\nfunction siblingSingleCount(args: Record<string, unknown>): number {\n\tif (isManagementCall(args) || isAsyncDetached(args)) return 0;\n\tif (Array.isArray(args.tasks) || Array.isArray(args.chain)) return 0;\n\treturn typeof args.task === \"string\" &&\n\t\targs.task.length > 0 &&\n\t\ttypeof args.description === \"string\" &&\n\t\targs.description.length > 0\n\t\t? 1\n\t\t: 0;\n}\n\ninterface AssistantMessageLike {\n\tcontent?: ReadonlyArray<{ type?: string; name?: string; arguments?: unknown }>;\n}\n\n/**\n * Parallel subagent count for the swarm gate. Uses this call's `tasks` / chain\n * `parallel` blocks, plus every other same-turn SINGLE `subagent` call so three\n * sibling singles still trip the >2 approval gate.\n */\nexport function effectiveSwarmCountForTurn(\n\targs: Record<string, unknown>,\n\tassistantMessage?: AssistantMessageLike,\n): number {\n\tconst own = effectiveSwarmCount(args);\n\tconst siblingSingles = (assistantMessage?.content ?? []).reduce((total, block) => {\n\t\tif (block.type !== \"toolCall\" || block.name !== \"subagent\") return total;\n\t\tconst siblingArgs =\n\t\t\tblock.arguments && typeof block.arguments === \"object\" && !Array.isArray(block.arguments)\n\t\t\t\t? (block.arguments as Record<string, unknown>)\n\t\t\t\t: undefined;\n\t\tif (!siblingArgs) return total;\n\t\treturn total + siblingSingleCount(siblingArgs);\n\t}, 0);\n\treturn Math.max(own, siblingSingles);\n}\n\ninterface BranchEntryLike {\n\ttype: string;\n\tmessage?: { role?: string; content?: unknown };\n}\n\nfunction messageText(content: unknown): string {\n\tif (typeof content === \"string\") return content;\n\tif (Array.isArray(content)) {\n\t\treturn content\n\t\t\t.filter((c) => c && typeof c === \"object\" && (c as { type?: unknown }).type === \"text\")\n\t\t\t.map((c) => String((c as { text?: unknown }).text ?? \"\"))\n\t\t\t.join(\"\");\n\t}\n\treturn \"\";\n}\n\n/**\n * True when the current turn started from an explicit /swarm prompt (the most\n * recent user message carries the literal `[SWARM MODE]` prefix). Both the TUI\n * and the gateway inject the same buildSwarmPrompt text, so this works on both\n * surfaces without extra state.\n */\nexport function isExplicitSwarmTurn(branch: readonly BranchEntryLike[]): boolean {\n\tfor (let i = branch.length - 1; i >= 0; i--) {\n\t\tconst entry = branch[i];\n\t\tif (entry.type !== \"message\" || entry.message?.role !== \"user\") continue;\n\t\treturn messageText(entry.message.content).startsWith(\"[SWARM MODE]\");\n\t}\n\treturn false;\n}\n"]}
@@ -1,119 +0,0 @@
1
- /**
2
- * lunR: reusable swarm prompt builder.
3
- *
4
- * Moved out of interactive-mode so the gateway can decompose tasks across
5
- * parallel subagents the same way the TUI does.
6
- */
7
- export function buildSwarmPrompt(task) {
8
- return `[SWARM MODE] Task: ${task}
9
- Act as an orchestrator. 1) Decompose into 3-8 independent subtasks. 2) Launch them
10
- in ONE parallel subagent call (async:false) as generic children, each with task,
11
- description, and permissions ("full" or "read-only"; omit permissions for full).
12
- Use read-only children for inspection/review and full children only when edits
13
- are required. Pick a model tier per subtask. 3) Synthesize the results and report.
14
- Rules: max 8 concurrent children; no nested fan-out; if a subtask fails, retry
15
- once with the heavy tier before giving up on it; keep your final report under
16
- 100 lines with per-subtask status.`;
17
- }
18
- /**
19
- * lunR: agent-swarm auto-activation gate helpers.
20
- *
21
- * When the model launches more than SWARM_APPROVAL_THRESHOLD parallel subagents
22
- * in one `subagent` `tasks`/`chain.parallel` call, or that many same-turn SINGLE
23
- * `subagent` calls, that counts as an auto-activated agent swarm and requires
24
- * user approval in every permission mode except `auto` (see core/permissions.ts).
25
- * An explicit /swarm turn is pre-approved because the user already asked for the swarm.
26
- */
27
- /** Parallel-subagent count above which the swarm approval gate engages. */
28
- export const SWARM_APPROVAL_THRESHOLD = 2;
29
- function countEntry(item) {
30
- const count = item && typeof item === "object" ? item.count : undefined;
31
- return typeof count === "number" && Number.isInteger(count) && count >= 1 ? count : 1;
32
- }
33
- function isManagementCall(args) {
34
- return typeof args.action === "string" && args.action.length > 0;
35
- }
36
- function isAsyncDetached(args) {
37
- return args.async === true && args.clarify !== true;
38
- }
39
- /**
40
- * Effective number of parallel subagents a `subagent` tool call will launch:
41
- * the `tasks` array (with `count` multipliers) plus any `chain` step `parallel`
42
- * fan-out blocks. Sequential chain steps and single-agent calls count as 0.
43
- * Dynamic `expand` fan-out has no static count and is not gated.
44
- */
45
- export function effectiveSwarmCount(args) {
46
- let total = 0;
47
- if (Array.isArray(args.tasks)) {
48
- for (const task of args.tasks)
49
- total += countEntry(task);
50
- }
51
- if (Array.isArray(args.chain)) {
52
- for (const step of args.chain) {
53
- const parallel = step && typeof step === "object" ? step.parallel : undefined;
54
- if (Array.isArray(parallel)) {
55
- for (const child of parallel)
56
- total += countEntry(child);
57
- }
58
- }
59
- }
60
- return total;
61
- }
62
- function siblingSingleCount(args) {
63
- if (isManagementCall(args) || isAsyncDetached(args))
64
- return 0;
65
- if (Array.isArray(args.tasks) || Array.isArray(args.chain))
66
- return 0;
67
- return typeof args.task === "string" &&
68
- args.task.length > 0 &&
69
- typeof args.description === "string" &&
70
- args.description.length > 0
71
- ? 1
72
- : 0;
73
- }
74
- /**
75
- * Parallel subagent count for the swarm gate. Uses this call's `tasks` / chain
76
- * `parallel` blocks, plus every other same-turn SINGLE `subagent` call so three
77
- * sibling singles still trip the >2 approval gate.
78
- */
79
- export function effectiveSwarmCountForTurn(args, assistantMessage) {
80
- const own = effectiveSwarmCount(args);
81
- const siblingSingles = (assistantMessage?.content ?? []).reduce((total, block) => {
82
- if (block.type !== "toolCall" || block.name !== "subagent")
83
- return total;
84
- const siblingArgs = block.arguments && typeof block.arguments === "object" && !Array.isArray(block.arguments)
85
- ? block.arguments
86
- : undefined;
87
- if (!siblingArgs)
88
- return total;
89
- return total + siblingSingleCount(siblingArgs);
90
- }, 0);
91
- return Math.max(own, siblingSingles);
92
- }
93
- function messageText(content) {
94
- if (typeof content === "string")
95
- return content;
96
- if (Array.isArray(content)) {
97
- return content
98
- .filter((c) => c && typeof c === "object" && c.type === "text")
99
- .map((c) => String(c.text ?? ""))
100
- .join("");
101
- }
102
- return "";
103
- }
104
- /**
105
- * True when the current turn started from an explicit /swarm prompt (the most
106
- * recent user message carries the literal `[SWARM MODE]` prefix). Both the TUI
107
- * and the gateway inject the same buildSwarmPrompt text, so this works on both
108
- * surfaces without extra state.
109
- */
110
- export function isExplicitSwarmTurn(branch) {
111
- for (let i = branch.length - 1; i >= 0; i--) {
112
- const entry = branch[i];
113
- if (entry.type !== "message" || entry.message?.role !== "user")
114
- continue;
115
- return messageText(entry.message.content).startsWith("[SWARM MODE]");
116
- }
117
- return false;
118
- }
119
- //# sourceMappingURL=swarm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"swarm.js","sourceRoot":"","sources":["../../src/core/swarm.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * lunR: reusable swarm prompt builder.\n *\n * Moved out of interactive-mode so the gateway can decompose tasks across\n * parallel subagents the same way the TUI does.\n */\n\nexport function buildSwarmPrompt(task: string): string {\n\treturn `[SWARM MODE] Task: ${task}\nAct as an orchestrator. 1) Decompose into 3-8 independent subtasks. 2) Launch them\nin ONE parallel subagent call (async:false) as generic children, each with task,\ndescription, and permissions (\"full\" or \"read-only\"; omit permissions for full).\nUse read-only children for inspection/review and full children only when edits\nare required. Pick a model tier per subtask. 3) Synthesize the results and report.\nRules: max 8 concurrent children; no nested fan-out; if a subtask fails, retry\nonce with the heavy tier before giving up on it; keep your final report under\n100 lines with per-subtask status.`;\n}\n\n/**\n * lunR: agent-swarm auto-activation gate helpers.\n *\n * When the model launches more than SWARM_APPROVAL_THRESHOLD parallel subagents\n * in one `subagent` `tasks`/`chain.parallel` call, or that many same-turn SINGLE\n * `subagent` calls, that counts as an auto-activated agent swarm and requires\n * user approval in every permission mode except `auto` (see core/permissions.ts).\n * An explicit /swarm turn is pre-approved because the user already asked for the swarm.\n */\n\n/** Parallel-subagent count above which the swarm approval gate engages. */\nexport const SWARM_APPROVAL_THRESHOLD = 2;\n\nfunction countEntry(item: unknown): number {\n\tconst count = item && typeof item === \"object\" ? (item as { count?: unknown }).count : undefined;\n\treturn typeof count === \"number\" && Number.isInteger(count) && count >= 1 ? count : 1;\n}\n\nfunction isManagementCall(args: Record<string, unknown>): boolean {\n\treturn typeof args.action === \"string\" && args.action.length > 0;\n}\n\nfunction isAsyncDetached(args: Record<string, unknown>): boolean {\n\treturn args.async === true && args.clarify !== true;\n}\n\n/**\n * Effective number of parallel subagents a `subagent` tool call will launch:\n * the `tasks` array (with `count` multipliers) plus any `chain` step `parallel`\n * fan-out blocks. Sequential chain steps and single-agent calls count as 0.\n * Dynamic `expand` fan-out has no static count and is not gated.\n */\nexport function effectiveSwarmCount(args: Record<string, unknown>): number {\n\tlet total = 0;\n\tif (Array.isArray(args.tasks)) {\n\t\tfor (const task of args.tasks) total += countEntry(task);\n\t}\n\tif (Array.isArray(args.chain)) {\n\t\tfor (const step of args.chain) {\n\t\t\tconst parallel = step && typeof step === \"object\" ? (step as { parallel?: unknown }).parallel : undefined;\n\t\t\tif (Array.isArray(parallel)) {\n\t\t\t\tfor (const child of parallel) total += countEntry(child);\n\t\t\t}\n\t\t}\n\t}\n\treturn total;\n}\n\nfunction siblingSingleCount(args: Record<string, unknown>): number {\n\tif (isManagementCall(args) || isAsyncDetached(args)) return 0;\n\tif (Array.isArray(args.tasks) || Array.isArray(args.chain)) return 0;\n\treturn typeof args.task === \"string\" &&\n\t\targs.task.length > 0 &&\n\t\ttypeof args.description === \"string\" &&\n\t\targs.description.length > 0\n\t\t? 1\n\t\t: 0;\n}\n\ninterface AssistantMessageLike {\n\tcontent?: ReadonlyArray<{ type?: string; name?: string; arguments?: unknown }>;\n}\n\n/**\n * Parallel subagent count for the swarm gate. Uses this call's `tasks` / chain\n * `parallel` blocks, plus every other same-turn SINGLE `subagent` call so three\n * sibling singles still trip the >2 approval gate.\n */\nexport function effectiveSwarmCountForTurn(\n\targs: Record<string, unknown>,\n\tassistantMessage?: AssistantMessageLike,\n): number {\n\tconst own = effectiveSwarmCount(args);\n\tconst siblingSingles = (assistantMessage?.content ?? []).reduce((total, block) => {\n\t\tif (block.type !== \"toolCall\" || block.name !== \"subagent\") return total;\n\t\tconst siblingArgs =\n\t\t\tblock.arguments && typeof block.arguments === \"object\" && !Array.isArray(block.arguments)\n\t\t\t\t? (block.arguments as Record<string, unknown>)\n\t\t\t\t: undefined;\n\t\tif (!siblingArgs) return total;\n\t\treturn total + siblingSingleCount(siblingArgs);\n\t}, 0);\n\treturn Math.max(own, siblingSingles);\n}\n\ninterface BranchEntryLike {\n\ttype: string;\n\tmessage?: { role?: string; content?: unknown };\n}\n\nfunction messageText(content: unknown): string {\n\tif (typeof content === \"string\") return content;\n\tif (Array.isArray(content)) {\n\t\treturn content\n\t\t\t.filter((c) => c && typeof c === \"object\" && (c as { type?: unknown }).type === \"text\")\n\t\t\t.map((c) => String((c as { text?: unknown }).text ?? \"\"))\n\t\t\t.join(\"\");\n\t}\n\treturn \"\";\n}\n\n/**\n * True when the current turn started from an explicit /swarm prompt (the most\n * recent user message carries the literal `[SWARM MODE]` prefix). Both the TUI\n * and the gateway inject the same buildSwarmPrompt text, so this works on both\n * surfaces without extra state.\n */\nexport function isExplicitSwarmTurn(branch: readonly BranchEntryLike[]): boolean {\n\tfor (let i = branch.length - 1; i >= 0; i--) {\n\t\tconst entry = branch[i];\n\t\tif (entry.type !== \"message\" || entry.message?.role !== \"user\") continue;\n\t\treturn messageText(entry.message.content).startsWith(\"[SWARM MODE]\");\n\t}\n\treturn false;\n}\n"]}