mindweave 2.5.1 → 3.0.0

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 (235) hide show
  1. package/README.md +50 -114
  2. package/dist/cli/App.js +578 -303
  3. package/dist/cli/App.js.map +1 -1
  4. package/dist/cli/analytics.js +27 -18
  5. package/dist/cli/analytics.js.map +1 -1
  6. package/dist/cli/attachments.js +34 -0
  7. package/dist/cli/attachments.js.map +1 -1
  8. package/dist/cli/bannerFit.js +70 -0
  9. package/dist/cli/bannerFit.js.map +1 -0
  10. package/dist/cli/bootstrap.js +41 -3
  11. package/dist/cli/bootstrap.js.map +1 -1
  12. package/dist/cli/commands.js +4 -1
  13. package/dist/cli/commands.js.map +1 -1
  14. package/dist/cli/components/ApprovalBox.js +3 -2
  15. package/dist/cli/components/ApprovalBox.js.map +1 -1
  16. package/dist/cli/components/BlockView.js +27 -6
  17. package/dist/cli/components/BlockView.js.map +1 -1
  18. package/dist/cli/components/FirstRunFrame.js +2 -1
  19. package/dist/cli/components/FirstRunFrame.js.map +1 -1
  20. package/dist/cli/components/KeyManager.js +5 -4
  21. package/dist/cli/components/KeyManager.js.map +1 -1
  22. package/dist/cli/components/KeySetup.js +29 -13
  23. package/dist/cli/components/KeySetup.js.map +1 -1
  24. package/dist/cli/components/MarathonBox.js +64 -0
  25. package/dist/cli/components/MarathonBox.js.map +1 -0
  26. package/dist/cli/components/McpMinitabs.js +8 -7
  27. package/dist/cli/components/McpMinitabs.js.map +1 -1
  28. package/dist/cli/components/Picker.js +4 -3
  29. package/dist/cli/components/Picker.js.map +1 -1
  30. package/dist/cli/components/PromptInput.js +47 -8
  31. package/dist/cli/components/PromptInput.js.map +1 -1
  32. package/dist/cli/components/PulseDot.js +42 -0
  33. package/dist/cli/components/PulseDot.js.map +1 -0
  34. package/dist/cli/components/SubagentView.js +9 -6
  35. package/dist/cli/components/SubagentView.js.map +1 -1
  36. package/dist/cli/components/TipLine.js +2 -1
  37. package/dist/cli/components/TipLine.js.map +1 -1
  38. package/dist/cli/components/ToolGroup.js +65 -49
  39. package/dist/cli/components/ToolGroup.js.map +1 -1
  40. package/dist/cli/components/ToolLine.js +20 -19
  41. package/dist/cli/components/ToolLine.js.map +1 -1
  42. package/dist/cli/components/TrustGate.js +2 -1
  43. package/dist/cli/components/TrustGate.js.map +1 -1
  44. package/dist/cli/components/minitabs.js +3 -2
  45. package/dist/cli/components/minitabs.js.map +1 -1
  46. package/dist/cli/desktopApp.js +45 -0
  47. package/dist/cli/desktopApp.js.map +1 -0
  48. package/dist/cli/help.js +1 -0
  49. package/dist/cli/help.js.map +1 -1
  50. package/dist/cli/inkOutputPatch.js +285 -0
  51. package/dist/cli/inkOutputPatch.js.map +1 -0
  52. package/dist/cli/inkSpeed.js +29 -0
  53. package/dist/cli/inkSpeed.js.map +1 -0
  54. package/dist/cli/inkSpeedLoader.js +47 -0
  55. package/dist/cli/inkSpeedLoader.js.map +1 -0
  56. package/dist/cli/inputText.js +30 -0
  57. package/dist/cli/inputText.js.map +1 -0
  58. package/dist/cli/keyManager.js +2 -1
  59. package/dist/cli/keyManager.js.map +1 -1
  60. package/dist/cli/keyPrefs.js +90 -0
  61. package/dist/cli/keyPrefs.js.map +1 -0
  62. package/dist/cli/keySetup.js +5 -2
  63. package/dist/cli/keySetup.js.map +1 -1
  64. package/dist/cli/marathonUi.js +113 -0
  65. package/dist/cli/marathonUi.js.map +1 -0
  66. package/dist/cli/markdown.js +63 -11
  67. package/dist/cli/markdown.js.map +1 -1
  68. package/dist/cli/modes.js +3 -3
  69. package/dist/cli/modes.js.map +1 -1
  70. package/dist/cli/prodEnv.js +43 -0
  71. package/dist/cli/prodEnv.js.map +1 -0
  72. package/dist/cli/revealPace.js +5 -5
  73. package/dist/cli/revealPace.js.map +1 -1
  74. package/dist/cli/revealQueue.js +120 -0
  75. package/dist/cli/revealQueue.js.map +1 -0
  76. package/dist/cli/theme.js +47 -0
  77. package/dist/cli/theme.js.map +1 -0
  78. package/dist/cli/toolDisplay.js +112 -18
  79. package/dist/cli/toolDisplay.js.map +1 -1
  80. package/dist/cli/transcript.js +1 -1
  81. package/dist/cli/transcript.js.map +1 -1
  82. package/dist/cli/virtualWindow.js +14 -2
  83. package/dist/cli/virtualWindow.js.map +1 -1
  84. package/dist/cli/wheelAccel.js +73 -0
  85. package/dist/cli/wheelAccel.js.map +1 -0
  86. package/dist/cli/widestLinePatch.js +48 -0
  87. package/dist/cli/widestLinePatch.js.map +1 -0
  88. package/dist/cli/workingVerb.js +88 -28
  89. package/dist/cli/workingVerb.js.map +1 -1
  90. package/dist/cli/wrap.js +1 -1
  91. package/dist/cli/wrap.js.map +1 -1
  92. package/dist/core/contextSettings.js +84 -0
  93. package/dist/core/contextSettings.js.map +1 -0
  94. package/dist/core/limitsView.js +40 -0
  95. package/dist/core/limitsView.js.map +1 -0
  96. package/dist/core/mcpServers.js +164 -0
  97. package/dist/core/mcpServers.js.map +1 -0
  98. package/dist/core/permissions.js +209 -0
  99. package/dist/core/permissions.js.map +1 -0
  100. package/dist/core/providerKeys.js +187 -0
  101. package/dist/core/providerKeys.js.map +1 -0
  102. package/dist/core/rulesSkills.js +142 -0
  103. package/dist/core/rulesSkills.js.map +1 -0
  104. package/dist/core/spendView.js +90 -0
  105. package/dist/core/spendView.js.map +1 -0
  106. package/dist/core/turnRunner.js +453 -60
  107. package/dist/core/turnRunner.js.map +1 -1
  108. package/dist/drivers/anthropic/client.js +24 -5
  109. package/dist/drivers/anthropic/client.js.map +1 -1
  110. package/dist/drivers/anthropic/manifest.js +15 -2
  111. package/dist/drivers/anthropic/manifest.js.map +1 -1
  112. package/dist/drivers/cerebras/manifest.js +6 -2
  113. package/dist/drivers/cerebras/manifest.js.map +1 -1
  114. package/dist/drivers/deepseek/manifest.js +12 -3
  115. package/dist/drivers/deepseek/manifest.js.map +1 -1
  116. package/dist/drivers/glm/manifest.js +3 -1
  117. package/dist/drivers/glm/manifest.js.map +1 -1
  118. package/dist/drivers/groq/manifest.js +5 -2
  119. package/dist/drivers/groq/manifest.js.map +1 -1
  120. package/dist/drivers/ollama/catalog.js +71 -0
  121. package/dist/drivers/ollama/catalog.js.map +1 -0
  122. package/dist/drivers/ollama/client.js +164 -0
  123. package/dist/drivers/ollama/client.js.map +1 -0
  124. package/dist/drivers/ollama/endpoint.js +42 -0
  125. package/dist/drivers/ollama/endpoint.js.map +1 -0
  126. package/dist/drivers/ollama/index.js +5 -0
  127. package/dist/drivers/ollama/index.js.map +1 -0
  128. package/dist/drivers/ollama/manifest.js +64 -0
  129. package/dist/drivers/ollama/manifest.js.map +1 -0
  130. package/dist/drivers/openai/client.js +10 -4
  131. package/dist/drivers/openai/client.js.map +1 -1
  132. package/dist/drivers/openai/manifest.js +46 -12
  133. package/dist/drivers/openai/manifest.js.map +1 -1
  134. package/dist/drivers/registry.js +11 -0
  135. package/dist/drivers/registry.js.map +1 -1
  136. package/dist/drivers/retryPolicy.js +26 -1
  137. package/dist/drivers/retryPolicy.js.map +1 -1
  138. package/dist/dynamo/auxModel.js +54 -0
  139. package/dist/dynamo/auxModel.js.map +1 -0
  140. package/dist/dynamo/engine.js +380 -99
  141. package/dist/dynamo/engine.js.map +1 -1
  142. package/dist/dynamo/guard.js +10 -0
  143. package/dist/dynamo/guard.js.map +1 -1
  144. package/dist/dynamo/liveMeter.js +25 -6
  145. package/dist/dynamo/liveMeter.js.map +1 -1
  146. package/dist/dynamo/marathon.js +409 -0
  147. package/dist/dynamo/marathon.js.map +1 -0
  148. package/dist/dynamo/marathonPrompt.js +45 -0
  149. package/dist/dynamo/marathonPrompt.js.map +1 -0
  150. package/dist/dynamo/model.js +6 -2
  151. package/dist/dynamo/model.js.map +1 -1
  152. package/dist/dynamo/toolBatches.js +58 -0
  153. package/dist/dynamo/toolBatches.js.map +1 -0
  154. package/dist/dynamo/usageLimits.js +446 -0
  155. package/dist/dynamo/usageLimits.js.map +1 -0
  156. package/dist/governor/freshness.js +10 -7
  157. package/dist/governor/freshness.js.map +1 -1
  158. package/dist/governor/index.js +76 -9
  159. package/dist/governor/index.js.map +1 -1
  160. package/dist/governor/write.js +43 -14
  161. package/dist/governor/write.js.map +1 -1
  162. package/dist/index.js +18 -151
  163. package/dist/index.js.map +1 -1
  164. package/dist/main.js +162 -0
  165. package/dist/main.js.map +1 -0
  166. package/dist/mcp/manager.js +18 -0
  167. package/dist/mcp/manager.js.map +1 -1
  168. package/dist/memory/allMetas.js +69 -0
  169. package/dist/memory/allMetas.js.map +1 -0
  170. package/dist/memory/compaction.js +69 -14
  171. package/dist/memory/compaction.js.map +1 -1
  172. package/dist/memory/earlier.js +15 -0
  173. package/dist/memory/earlier.js.map +1 -0
  174. package/dist/memory/profile.js +93 -0
  175. package/dist/memory/profile.js.map +1 -0
  176. package/dist/memory/rewind.js +262 -0
  177. package/dist/memory/rewind.js.map +1 -0
  178. package/dist/memory/session.js +42 -10
  179. package/dist/memory/session.js.map +1 -1
  180. package/dist/memory/sessionMemory.js +48 -13
  181. package/dist/memory/sessionMemory.js.map +1 -1
  182. package/dist/memory/sessionMemoryCompact.js +1 -1
  183. package/dist/memory/sessionMemoryCompact.js.map +1 -1
  184. package/dist/memory/sessionTitle.js +50 -0
  185. package/dist/memory/sessionTitle.js.map +1 -0
  186. package/dist/memory/store.js +42 -1
  187. package/dist/memory/store.js.map +1 -1
  188. package/dist/memory/types.js.map +1 -1
  189. package/dist/tools/askUser.js +14 -0
  190. package/dist/tools/askUser.js.map +1 -1
  191. package/dist/tools/backgroundShells.js +208 -5
  192. package/dist/tools/backgroundShells.js.map +1 -1
  193. package/dist/tools/browser.js +176 -0
  194. package/dist/tools/browser.js.map +1 -0
  195. package/dist/tools/cdp.js +165 -0
  196. package/dist/tools/cdp.js.map +1 -0
  197. package/dist/tools/checkpoints.js +208 -5
  198. package/dist/tools/checkpoints.js.map +1 -1
  199. package/dist/tools/deferredNative.js +2 -0
  200. package/dist/tools/deferredNative.js.map +1 -1
  201. package/dist/tools/exitPlan.js +4 -0
  202. package/dist/tools/exitPlan.js.map +1 -1
  203. package/dist/tools/hiddenDesktop.js +273 -0
  204. package/dist/tools/hiddenDesktop.js.map +1 -0
  205. package/dist/tools/listeningPorts.js +134 -0
  206. package/dist/tools/listeningPorts.js.map +1 -0
  207. package/dist/tools/mcpSearch.js +8 -0
  208. package/dist/tools/mcpSearch.js.map +1 -1
  209. package/dist/tools/mindweaveStatus.js +1 -1
  210. package/dist/tools/mindweaveStatus.js.map +1 -1
  211. package/dist/tools/registry.js +3 -0
  212. package/dist/tools/registry.js.map +1 -1
  213. package/dist/tools/runCommand.js +107 -6
  214. package/dist/tools/runCommand.js.map +1 -1
  215. package/dist/tools/screenshot.js +4 -6
  216. package/dist/tools/screenshot.js.map +1 -1
  217. package/dist/tools/screenshotWin.js +26 -9
  218. package/dist/tools/screenshotWin.js.map +1 -1
  219. package/dist/tools/stateCheckpoint.js +128 -0
  220. package/dist/tools/stateCheckpoint.js.map +1 -0
  221. package/dist/tools/todo.js +6 -0
  222. package/dist/tools/todo.js.map +1 -1
  223. package/dist/tools/ui.js +1295 -0
  224. package/dist/tools/ui.js.map +1 -0
  225. package/dist/tools/uiHide.js +356 -0
  226. package/dist/tools/uiHide.js.map +1 -0
  227. package/dist/tools/uiPage.js +861 -0
  228. package/dist/tools/uiPage.js.map +1 -0
  229. package/dist/tools/uiWin.js +506 -0
  230. package/dist/tools/uiWin.js.map +1 -0
  231. package/dist/tools/webFetch.js +32 -25
  232. package/dist/tools/webFetch.js.map +1 -1
  233. package/dist/tools/webSearch.js +12 -0
  234. package/dist/tools/webSearch.js.map +1 -1
  235. package/package.json +78 -78
@@ -0,0 +1,50 @@
1
+ /**
2
+ * sessionTitle.ts — a session's name, from the notes it already keeps.
3
+ *
4
+ * The session notes (sessionMemory.ts) open with a "Session Title" section the model
5
+ * fills in as part of the update it already makes. Lists named a session by its first
6
+ * message instead ("hi hi"), which says nothing about the work. Reading the title back
7
+ * out costs nothing: no call of its own, just the notes that are already on disk.
8
+ */
9
+ /** The title the notes give the session, or undefined while they give none. */
10
+ export function sessionTitle(notes) {
11
+ if (!notes)
12
+ return undefined;
13
+ const lines = notes.split(/\r?\n/);
14
+ const at = lines.findIndex((l) => /^#\s+Session Title\s*$/i.test(l.trim()));
15
+ if (at < 0)
16
+ return undefined;
17
+ for (const raw of lines.slice(at + 1)) {
18
+ const line = raw.trim();
19
+ if (line.startsWith("#"))
20
+ return undefined; // the next section: no title written yet
21
+ // Blank lines, and the template's own instruction under the heading. Only that one
22
+ // line: a model may write the title itself in the same italics.
23
+ if (!line || /^_A short and distinctive .*title for the session/i.test(line))
24
+ continue;
25
+ return shortTitle(line.replace(/^[*_`"]+|[*_`"]+$/g, ""));
26
+ }
27
+ return undefined;
28
+ }
29
+ const TITLE_MAX = 48;
30
+ /**
31
+ * A title short enough to name a session in a list. Notes written before the template
32
+ * asked for a few words ran long ("Menteus monorepo: building events package (EventBus
33
+ * + EventStream) atop designed skeleton"): the bracketed detail goes, a leading
34
+ * "project: " goes when what follows says enough (the project is already on screen),
35
+ * and what is still too long is cut at a word.
36
+ */
37
+ function shortTitle(raw) {
38
+ let t = raw.replace(/\s*\([^)]*\)/g, "").replace(/\s+/g, " ").trim();
39
+ const colon = t.indexOf(": ");
40
+ if (colon > 0 && colon < 40 && t.slice(colon + 2).split(" ").length >= 2)
41
+ t = t.slice(colon + 2);
42
+ t = t.charAt(0).toUpperCase() + t.slice(1);
43
+ if (t.length > TITLE_MAX) {
44
+ const cut = t.slice(0, TITLE_MAX - 1);
45
+ const space = cut.lastIndexOf(" ");
46
+ t = `${(space > 20 ? cut.slice(0, space) : cut).replace(/[\s,;:.–—-]+$/, "")}…`;
47
+ }
48
+ return t || undefined;
49
+ }
50
+ //# sourceMappingURL=sessionTitle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionTitle.js","sourceRoot":"","sources":["../../src/memory/sessionTitle.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,KAAyB;IACpD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5E,IAAI,EAAE,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC,CAAC,yCAAyC;QACrF,mFAAmF;QACnF,gEAAgE;QAChE,IAAI,CAAC,IAAI,IAAI,oDAAoD,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QACvF,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACjG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3C,IAAI,CAAC,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,GAAG,CAAC;IAClF,CAAC;IACD,OAAO,CAAC,IAAI,SAAS,CAAC;AACxB,CAAC"}
@@ -24,6 +24,7 @@ import { homedir } from "node:os";
24
24
  import { join } from "node:path";
25
25
  import { writeFileAtomic } from "../tools/atomicWrite.js";
26
26
  import { collapsePastes } from "./pastedText.js";
27
+ import { sessionTitle } from "./sessionTitle.js";
27
28
  /** Turn a project path into a single safe directory name (e.g. `D:\proj` → `D--proj`). */
28
29
  export function sanitizeProjectPath(cwd) {
29
30
  return cwd.replace(/[/\\:]+/g, "-").replace(/^-+|-+$/g, "") || "root";
@@ -63,6 +64,11 @@ export function sessionDir(projectCwd) {
63
64
  export function transcriptPath(projectCwd, id) {
64
65
  return join(sessionDir(projectCwd), `${id}.jsonl`);
65
66
  }
67
+ /** What compaction took out of a session's transcript, kept for redrawing the chat
68
+ * (see memory/earlier.ts). Appended to, never rewritten. */
69
+ function earlierPath(projectCwd, id) {
70
+ return join(sessionDir(projectCwd), `${id}.earlier.jsonl`);
71
+ }
66
72
  /** Sidecar file holding a session's maintained "session memory" notes. */
67
73
  function notesPath(projectCwd, id) {
68
74
  return join(sessionDir(projectCwd), `${id}.notes.md`);
@@ -76,6 +82,16 @@ export async function loadSessionNotes(projectCwd, id) {
76
82
  return "";
77
83
  }
78
84
  }
85
+ /** Where a session's undo history is kept on disk (see Checkpoints.persistTo). */
86
+ export function checkpointDir(projectCwd, id) {
87
+ return join(sessionDir(projectCwd), `${id}.checkpoints`);
88
+ }
89
+ /** Delete a session's notes sidecar. Saving only ever writes notes that exist, so notes
90
+ * that stopped being true (a rewind took back the turns they describe) have to be
91
+ * removed on purpose, or a resume would load them again. */
92
+ export async function clearSessionNotes(projectCwd, id) {
93
+ await fs.rm(notesPath(projectCwd, id), { force: true }).catch(() => { });
94
+ }
79
95
  function metaPath(projectCwd, id) {
80
96
  return join(sessionDir(projectCwd), `${id}.meta.json`);
81
97
  }
@@ -137,14 +153,23 @@ export async function saveSession(session) {
137
153
  // The same reasoning already protects the user's SOURCE files; their session was
138
154
  // the one thing still written the unsafe way.
139
155
  await writeFileAtomic(transcriptPath(session.cwd, session.id), lines + "\n");
156
+ // What compaction took out since the last save, added to the end of its own file.
157
+ // Appended rather than rewritten: it only ever grows, and it can grow large.
158
+ if (session.earlierUnsaved && session.earlierUnsaved.length > 0) {
159
+ const gone = session.earlierUnsaved;
160
+ await fs.appendFile(earlierPath(session.cwd, session.id), gone.map((e) => JSON.stringify(e)).join("\n") + "\n");
161
+ session.earlierUnsaved = undefined;
162
+ }
140
163
  // Extra roots = everything on the tool context beyond the primary (session.cwd).
141
164
  const extraRoots = (session.toolContext.roots ?? []).filter((r) => r !== session.cwd);
165
+ const title = sessionTitle(session.sessionMemory);
142
166
  const meta = {
143
167
  id: session.id,
144
168
  cwd: session.cwd,
145
169
  createdAt: session.createdAt,
146
170
  updatedAt: Date.now(),
147
171
  firstPrompt: clip(firstUserText(session.transcript)),
172
+ ...(title ? { title } : {}),
148
173
  lastPrompt: clip(lastUserText(session.transcript)),
149
174
  entryCount: session.transcript.length,
150
175
  // Unconditional: a session with no model recorded is one whose behaviour cannot
@@ -158,11 +183,14 @@ export async function saveSession(session) {
158
183
  // totals above are identical whether a turn made one expensive call or six cheap
159
184
  // ones, and that difference is the whole answer.
160
185
  ...(session.callLog && session.callLog.length > 0 ? { callLog: session.callLog } : {}),
186
+ ...(session.contextOverhead ? { contextOverhead: session.contextOverhead } : {}),
161
187
  // Deferred tools the model surfaced this session, so a resume re-advertises them
162
188
  // instead of stripping a tool it was mid-use of (see registry.toolSchemas).
163
189
  ...(session.toolContext.activatedTools && session.toolContext.activatedTools.size > 0
164
190
  ? { activatedTools: [...session.toolContext.activatedTools] }
165
191
  : {}),
192
+ // Only once a Marathon has actually been started on this session.
193
+ ...(session.marathon ? { marathon: session.marathon } : {}),
166
194
  };
167
195
  await writeFileAtomic(metaPath(session.cwd, session.id), JSON.stringify(meta, null, 2));
168
196
  // Session-memory notes sidecar (the maintained running state), when present.
@@ -177,8 +205,15 @@ export async function saveSession(session) {
177
205
  }
178
206
  /** Load a session's transcript from disk, or null if it isn't there / is unreadable. */
179
207
  export async function loadTranscript(projectCwd, id) {
208
+ return readEntries(transcriptPath(projectCwd, id));
209
+ }
210
+ /** What compaction took out of a session (see memory/earlier.ts), or [] if nothing was. */
211
+ export async function loadEarlier(projectCwd, id) {
212
+ return (await readEntries(earlierPath(projectCwd, id))) ?? [];
213
+ }
214
+ async function readEntries(path) {
180
215
  try {
181
- const raw = await fs.readFile(transcriptPath(projectCwd, id), "utf8");
216
+ const raw = await fs.readFile(path, "utf8");
182
217
  const entries = [];
183
218
  for (const line of raw.split("\n")) {
184
219
  const trimmed = line.trim();
@@ -230,6 +265,12 @@ export async function listSessions(projectCwd) {
230
265
  // each reading "0 msgs" in /continue and each counted as an earlier session.
231
266
  if (meta.entryCount === 0)
232
267
  continue;
268
+ // Saved before titles were recorded: its notes may already have one.
269
+ if (!meta.title) {
270
+ const title = sessionTitle(await loadSessionNotes(projectCwd, meta.id));
271
+ if (title)
272
+ meta.title = title;
273
+ }
233
274
  metas.push(meta);
234
275
  }
235
276
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":"AAqIA;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAC7D,OAAO,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;AAC/F,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":"AA8IA;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAC7D,OAAO,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;AAC/F,CAAC"}
@@ -6,6 +6,10 @@ const askUserDef = {
6
6
  * call to be made, not a question put back to the user. */
7
7
  deferred: true,
8
8
  readOnly: true,
9
+ // Never alongside other calls: while a question waits on the user, nothing else
10
+ // may run or appear. The engine finishes the parallel lane first, and everything
11
+ // after this waits for the answer.
12
+ isConcurrencySafe: () => false,
9
13
  // The old text promised "the user's choice is returned to you" with no account of the
10
14
  // two ways that does not happen — dismissal, and no channel at all. Both now return a
11
15
  // plain instruction to carry on, so the model must know they are possible or it will
@@ -56,6 +60,16 @@ const askUserDef = {
56
60
  return failQuietly("`question` is required.");
57
61
  if (options.length < 2)
58
62
  return failQuietly("provide at least 2 concrete `options`.");
63
+ // A Marathon closes questions after its opening turn: the person delegated the whole
64
+ // run, and a question that waits for them would stall it indefinitely.
65
+ if (ctx.noQuestions) {
66
+ return {
67
+ output: "Questions are closed for this run: it is working on its own now, so nobody will " +
68
+ "answer. Choose the most reasonable option yourself, note the assumption where the " +
69
+ "user will see it (your task list or your next reply), and keep going.",
70
+ summary: "ask_user closed — decide and continue",
71
+ };
72
+ }
59
73
  // No approval channel (headless run / tests): can't ask — tell the model to
60
74
  // proceed on its best judgment rather than stall.
61
75
  if (!ctx.requestApproval) {
@@ -1 +1 @@
1
- {"version":3,"file":"askUser.js","sourceRoot":"","sources":["../../src/tools/askUser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"askUser.js","sourceRoot":"","sources":["../../src/tools/askUser.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,7 @@
24
24
  * Client-side, like the alternator lanes: it holds live process handles, never
25
25
  * crosses the engine↔brain wire. All children are killed on process exit.
26
26
  */
27
+ import { listListeners, ownerOf, parentMap } from "./listeningPorts.js";
27
28
  import { promises as fs } from "node:fs";
28
29
  import { killTree, killTreeSync } from "./killTree.js";
29
30
  import { OutputReader, removeOutputFile, sizeOf } from "./commandOutput.js";
@@ -77,6 +78,8 @@ function envMs(name, fallback) {
77
78
  }
78
79
  /** How often the stall watchdog scans running shells. */
79
80
  const STALL_CHECK_MS = envMs("MINDWEAVE_STALL_CHECK_MS", 5_000);
81
+ /** How often the running shells are checked for ports their processes opened. */
82
+ const PORT_WATCH_MS = envMs("MINDWEAVE_PORT_WATCH_MS", 3_000);
80
83
  /**
81
84
  * A backgrounded command that has printed nothing for this long AND whose last line
82
85
  * looks like an interactive prompt is treated as blocked on input. Sooner than the
@@ -226,6 +229,7 @@ export class BackgroundShells {
226
229
  exitGraceMs;
227
230
  stallPromptMs;
228
231
  stallSilentMs;
232
+ portWatchMs;
229
233
  seq = 0;
230
234
  shells = new Map();
231
235
  onChange = null;
@@ -237,11 +241,12 @@ export class BackgroundShells {
237
241
  * per case was 73% of the whole run's wall time, and that cost lands again on
238
242
  * every contributor and every CI job.
239
243
  */
240
- constructor(startupGraceMs = STARTUP_GRACE_MS, exitGraceMs = EXIT_GRACE_MS, stallPromptMs = STALL_PROMPT_MS, stallSilentMs = STALL_SILENT_MS) {
244
+ constructor(startupGraceMs = STARTUP_GRACE_MS, exitGraceMs = EXIT_GRACE_MS, stallPromptMs = STALL_PROMPT_MS, stallSilentMs = STALL_SILENT_MS, portWatchMs = PORT_WATCH_MS) {
241
245
  this.startupGraceMs = startupGraceMs;
242
246
  this.exitGraceMs = exitGraceMs;
243
247
  this.stallPromptMs = stallPromptMs;
244
248
  this.stallSilentMs = stallSilentMs;
249
+ this.portWatchMs = portWatchMs;
245
250
  active.add(this);
246
251
  registerCleanup();
247
252
  // The watchdog. A backgrounded command is told to end its turn, so a process that
@@ -250,6 +255,101 @@ export class BackgroundShells {
250
255
  this.stallTimer = setInterval(() => this.checkStalls(), STALL_CHECK_MS);
251
256
  this.stallTimer.unref?.();
252
257
  }
258
+ /**
259
+ * The port watch. A background command's own events are coming up (a server alive
260
+ * past its startup grace), ending and stalling, and none of them is "the app it was
261
+ * building has opened". A Tauri build announces its dev server long before the app
262
+ * itself exists; an agent that ends its turn to wait for the app then waits for an
263
+ * event that never comes. What the app DOES do when it opens is listen on a port (its
264
+ * dev server, its debugging port), so the running shells are watched for ports their
265
+ * own processes open, and a new one is news worth waking the agent for.
266
+ */
267
+ portTimer = null;
268
+ portBusy = false;
269
+ /** Listening process → the shell it descends from (null: not ours). Traced once. */
270
+ portOwners = new Map();
271
+ startPortWatch() {
272
+ if (this.portTimer || this.portWatchMs <= 0)
273
+ return;
274
+ this.portTimer = setInterval(() => void this.checkPorts(), this.portWatchMs);
275
+ this.portTimer.unref?.();
276
+ }
277
+ /**
278
+ * One scan for ports the running shells' processes opened. `source` is injectable for
279
+ * tests; production uses the operating system's own listing.
280
+ *
281
+ * A port has to be seen on two scans in a row before it counts, so a port open for a
282
+ * moment (a test suite's throwaway server) is not announced as an app coming up. For
283
+ * a server still inside its startup grace, a confirmed port IS it coming up, sooner
284
+ * than the grace would say; for anything else it is an "opened" event.
285
+ */
286
+ async checkPorts(source = { listListeners, parentMap }) {
287
+ if (this.portBusy)
288
+ return;
289
+ const running = [...this.shells.values()].filter((e) => e.status === "running" && e.child?.pid && e.notify !== "never");
290
+ if (running.length === 0) {
291
+ if (this.portTimer) {
292
+ clearInterval(this.portTimer);
293
+ this.portTimer = null;
294
+ }
295
+ return;
296
+ }
297
+ this.portBusy = true;
298
+ try {
299
+ const listeners = await source.listListeners();
300
+ const live = new Set(listeners.map((l) => l.pid));
301
+ for (const pid of this.portOwners.keys())
302
+ if (!live.has(pid))
303
+ this.portOwners.delete(pid);
304
+ const untraced = listeners.filter((l) => !this.portOwners.has(l.pid));
305
+ if (untraced.length) {
306
+ const parents = await source.parentMap();
307
+ const roots = new Map(running.map((e) => [e.child.pid, e.id]));
308
+ const rootSet = new Set(roots.keys());
309
+ for (const l of untraced) {
310
+ const root = ownerOf(l.pid, parents, rootSet);
311
+ this.portOwners.set(l.pid, root === null ? null : roots.get(root));
312
+ }
313
+ }
314
+ let changed = false;
315
+ const now = Date.now();
316
+ for (const l of listeners) {
317
+ const id = this.portOwners.get(l.pid);
318
+ if (id === null || id === undefined)
319
+ continue;
320
+ const entry = this.shells.get(id);
321
+ if (!entry || entry.status !== "running" || entry.portsSeen.has(l.port))
322
+ continue;
323
+ if (!entry.portCandidates.has(l.port)) {
324
+ entry.portCandidates.set(l.port, now);
325
+ continue;
326
+ }
327
+ entry.portCandidates.delete(l.port);
328
+ entry.portsSeen.add(l.port);
329
+ if (entry.notify === "on_failure" && !entry.readyReported) {
330
+ // Not yet told it is up: that note says it, with every port it has opened by
331
+ // then, so a port opening meanwhile is not a second note about the same moment.
332
+ if (entry.readyTimer) {
333
+ clearTimeout(entry.readyTimer);
334
+ entry.readyTimer = null;
335
+ }
336
+ entry.ready = true;
337
+ }
338
+ else {
339
+ entry.openedPending.push(l.port);
340
+ }
341
+ changed = true;
342
+ }
343
+ if (changed)
344
+ this.emit();
345
+ }
346
+ catch {
347
+ // A scan that fails says nothing; the next one tries again.
348
+ }
349
+ finally {
350
+ this.portBusy = false;
351
+ }
352
+ }
253
353
  /** Subscribe to state changes (start / finish / kill) — the UI re-renders. */
254
354
  setOnChange(cb) {
255
355
  this.onChange = cb;
@@ -286,6 +386,9 @@ export class BackgroundShells {
286
386
  pollTimer: null,
287
387
  cwdFile: opts.cwdFile,
288
388
  tempFile: opts.tempFile,
389
+ portsSeen: new Set(),
390
+ portCandidates: new Map(),
391
+ openedPending: [],
289
392
  };
290
393
  this.shells.set(id, entry);
291
394
  if (opts.outputPath) {
@@ -302,6 +405,8 @@ export class BackgroundShells {
302
405
  child.stdout?.on("data", collect);
303
406
  child.stderr?.on("data", collect);
304
407
  }
408
+ if (entry.notify !== "never")
409
+ this.startPortWatch();
305
410
  // The readiness signal. A server that is still alive after the startup grace has
306
411
  // come up, and that is the one positive event worth reporting for something that
307
412
  // never "finishes". Without it the model was told to promise a report it could not
@@ -351,8 +456,8 @@ export class BackgroundShells {
351
456
  if (chunk)
352
457
  this.append(entry, chunk);
353
458
  if (entry.outputPath && (await sizeOf(entry.outputPath)) > MAX_OUTPUT_BYTES) {
354
- this.append(entry, `
355
- [output passed ${MAX_OUTPUT_DISPLAY}; the command was stopped]
459
+ this.append(entry, `
460
+ [output passed ${MAX_OUTPUT_DISPLAY}; the command was stopped]
356
461
  `);
357
462
  this.kill(entry.id, "system");
358
463
  }
@@ -412,7 +517,9 @@ export class BackgroundShells {
412
517
  if (entry.status !== "running")
413
518
  return;
414
519
  entry.status = killed ? "killed" : "exited";
415
- entry.exitCode = code;
520
+ // Windows hands a negative exit code back unsigned (-1 arrives as 4294967295), the
521
+ // same correction run_command makes for a command in the foreground.
522
+ entry.exitCode = code !== null && code > 0x7fffffff ? code - 0x100000000 : code;
416
523
  if (signal)
417
524
  entry.signal = signal;
418
525
  entry.finishedAt = Date.now();
@@ -466,6 +573,70 @@ export class BackgroundShells {
466
573
  void fs.rm(entry.tempFile, { force: true }).catch(() => { });
467
574
  this.emit();
468
575
  }
576
+ /**
577
+ * Watch a shell that was JUST started, for a few seconds, and say what became of it.
578
+ *
579
+ * It exists for apps and servers. The old way was to hand the model "started" and let it end
580
+ * its turn, then wake it ten seconds later with "it came up". Two replies for one launch, the
581
+ * second often repeating the first, and the user looking at an open window for several seconds
582
+ * before the agent noticed. Waiting here, inside the call that started it, lets the one reply
583
+ * be written knowing the outcome.
584
+ *
585
+ * up still alive when `ms` ran out, or a port was seen listening: it came up
586
+ * ended it exited inside the window: it never came up, and the output says why
587
+ * aborted the turn was interrupted while waiting
588
+ *
589
+ * Whichever it is, the model is being told RIGHT NOW in the tool result, so the matching
590
+ * background note is marked as told. Left unmarked, the model would hear the same news a
591
+ * second time and reply to it, which is the duplicate this was written to remove.
592
+ */
593
+ async settle(id, ms, signal) {
594
+ const entry = this.shells.get(id);
595
+ if (!entry)
596
+ return null;
597
+ const deadline = Date.now() + Math.max(0, ms);
598
+ let outcome = "up";
599
+ for (;;) {
600
+ if (signal?.aborted) {
601
+ outcome = "aborted";
602
+ break;
603
+ }
604
+ // Exited, and not merely about to be finalized: the process object knows before the
605
+ // manager's own bookkeeping does, which waits for the pipes to close.
606
+ if (entry.status !== "running" || (entry.child && entry.child.exitCode !== null)) {
607
+ outcome = "ended";
608
+ break;
609
+ }
610
+ if (entry.portsSeen.size > 0 || Date.now() >= deadline)
611
+ break;
612
+ await new Promise((r) => setTimeout(r, 50));
613
+ }
614
+ // Let the last of its output reach the buffer before it is read.
615
+ if (outcome === "ended") {
616
+ const end = Date.now() + this.exitGraceMs + 500;
617
+ while (entry.status === "running" && Date.now() < end)
618
+ await new Promise((r) => setTimeout(r, 25));
619
+ }
620
+ const fresh = entry.reader ? await entry.reader.next(POLL_READ_BYTES) : "";
621
+ if (fresh)
622
+ this.append(entry, fresh);
623
+ const output = stripNativeStderrNoise(entry.seen.slice(Math.max(0, entry.seen.length - TAIL_CHARS)));
624
+ // What was just handed over is not handed over again.
625
+ entry.notifiedUpto = entry.seen.length;
626
+ if (outcome === "up") {
627
+ entry.ready = true;
628
+ entry.readyReported = true;
629
+ if (entry.readyTimer) {
630
+ clearTimeout(entry.readyTimer);
631
+ entry.readyTimer = null;
632
+ }
633
+ this.emit();
634
+ }
635
+ else if (outcome === "ended") {
636
+ entry.reported = true;
637
+ }
638
+ return { outcome, info: view(entry), output };
639
+ }
469
640
  /** New output since the last read of this shell, plus its current status. */
470
641
  async read(id) {
471
642
  const entry = this.shells.get(id);
@@ -484,6 +655,24 @@ export class BackgroundShells {
484
655
  }
485
656
  return { info: view(entry), chunk };
486
657
  }
658
+ /**
659
+ * The last `maxChars` of a shell's output, for a UI showing the log beside the chat.
660
+ *
661
+ * Unlike `read`, this does NOT move the handed-out position: the agent's next `read`
662
+ * still gets everything it has not seen. A user glancing at the log must never make the
663
+ * agent miss the output that says the build failed.
664
+ */
665
+ async peek(id, maxChars = 8_000) {
666
+ const entry = this.shells.get(id);
667
+ if (!entry)
668
+ return null;
669
+ const fresh = entry.reader ? await entry.reader.next(POLL_READ_BYTES) : "";
670
+ if (fresh)
671
+ this.append(entry, fresh);
672
+ const all = stripNativeStderrNoise(entry.seen);
673
+ const clipped = all.length > maxChars || entry.truncated === true;
674
+ return { info: view(entry), tail: all.length > maxChars ? all.slice(all.length - maxChars) : all, clipped };
675
+ }
487
676
  /**
488
677
  * Kill a running shell (whole tree). Returns false if it isn't running.
489
678
  *
@@ -519,7 +708,8 @@ export class BackgroundShells {
519
708
  pendingCount() {
520
709
  return [...this.shells.values()].filter((e) => (e.status !== "running" && !e.reported && e.wakeOnEnd) ||
521
710
  (e.ready && !e.readyReported) ||
522
- (e.stallReason !== undefined && !e.stallReported)).length;
711
+ (e.stallReason !== undefined && !e.stallReported) ||
712
+ (e.status === "running" && e.openedPending.length > 0)).length;
523
713
  }
524
714
  /** One-shot for the UI: shells that came up or stopped and aren't in the chat yet. */
525
715
  takeUiEvents() {
@@ -582,6 +772,14 @@ export class BackgroundShells {
582
772
  out.push({ info: view(entry), kind: "ready", tail: takeDelta(), wake: true });
583
773
  emitted = true;
584
774
  }
775
+ // It opened a port after it had already come up (or it is a command only reported
776
+ // at its end): the app it was building has opened. Not for one that has ended since,
777
+ // which says so itself.
778
+ if (entry.openedPending.length && entry.status === "running") {
779
+ const ports = entry.openedPending.splice(0);
780
+ out.push({ info: view(entry), kind: "opened", tail: takeDelta(), wake: true, ports });
781
+ emitted = true;
782
+ }
585
783
  if (entry.stallReason !== undefined && !entry.stallReported) {
586
784
  entry.stallReported = true;
587
785
  // A stall is ABOUT the silence, so it shows the last thing the shell SAID rather
@@ -641,6 +839,10 @@ export class BackgroundShells {
641
839
  clearInterval(this.stallTimer);
642
840
  this.stallTimer = null;
643
841
  }
842
+ if (this.portTimer) {
843
+ clearInterval(this.portTimer);
844
+ this.portTimer = null;
845
+ }
644
846
  active.delete(this);
645
847
  }
646
848
  emit() {
@@ -663,6 +865,7 @@ function view(e) {
663
865
  ...(e.truncated ? { truncated: true } : {}),
664
866
  ...(e.stallReason ? { stallReason: e.stallReason } : {}),
665
867
  ...(detectPort(e.seen) !== undefined ? { port: detectPort(e.seen) } : {}),
868
+ ...(e.portsSeen.size ? { listening: [...e.portsSeen] } : {}),
666
869
  };
667
870
  }
668
871
  /** Kill any background processes still running when the process exits. */