mindweave 2.4.9 → 2.5.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 (52) hide show
  1. package/README.md +1 -0
  2. package/dist/cli/App.js +46 -7
  3. package/dist/cli/App.js.map +1 -1
  4. package/dist/cli/commandArgs.js +7 -1
  5. package/dist/cli/commandArgs.js.map +1 -1
  6. package/dist/cli/commands.js +1 -0
  7. package/dist/cli/commands.js.map +1 -1
  8. package/dist/cli/components/ApprovalBox.js +10 -1
  9. package/dist/cli/components/ApprovalBox.js.map +1 -1
  10. package/dist/cli/components/McpMinitabs.js +1 -1
  11. package/dist/cli/components/Picker.js +1 -1
  12. package/dist/cli/components/Picker.js.map +1 -1
  13. package/dist/cli/components/ToolLine.js +1 -1
  14. package/dist/cli/components/ToolLine.js.map +1 -1
  15. package/dist/cli/feedback.js +223 -0
  16. package/dist/cli/feedback.js.map +1 -0
  17. package/dist/cli/framebuffer/writer.js +1 -1
  18. package/dist/cli/toolDisplay.js +4 -3
  19. package/dist/cli/toolDisplay.js.map +1 -1
  20. package/dist/dynamo/engine.js +152 -99
  21. package/dist/dynamo/engine.js.map +1 -1
  22. package/dist/governor/skills.js +1 -1
  23. package/dist/governor/write.js +61 -0
  24. package/dist/governor/write.js.map +1 -1
  25. package/dist/mcp/configWrite.js +1 -1
  26. package/dist/memory/compaction.js +9 -1
  27. package/dist/memory/compaction.js.map +1 -1
  28. package/dist/memory/store.js +8 -1
  29. package/dist/memory/store.js.map +1 -1
  30. package/dist/tools/backgroundShells.js +4 -3
  31. package/dist/tools/backgroundShells.js.map +1 -1
  32. package/dist/tools/deferredNative.js +13 -4
  33. package/dist/tools/deferredNative.js.map +1 -1
  34. package/dist/tools/governorTools.js +113 -9
  35. package/dist/tools/governorTools.js.map +1 -1
  36. package/dist/tools/mcpAdd.js +87 -4
  37. package/dist/tools/mcpAdd.js.map +1 -1
  38. package/dist/tools/mcpSearch.js +5 -4
  39. package/dist/tools/mcpSearch.js.map +1 -1
  40. package/dist/tools/mindweaveStatus.js +113 -0
  41. package/dist/tools/mindweaveStatus.js.map +1 -0
  42. package/dist/tools/nativeStderr.js +27 -0
  43. package/dist/tools/nativeStderr.js.map +1 -0
  44. package/dist/tools/registry.js +6 -4
  45. package/dist/tools/registry.js.map +1 -1
  46. package/dist/tools/runCommand.js +53 -18
  47. package/dist/tools/runCommand.js.map +1 -1
  48. package/dist/tools/screenshot.js +17 -4
  49. package/dist/tools/screenshot.js.map +1 -1
  50. package/dist/tools/todo.js +5 -5
  51. package/dist/tools/todo.js.map +1 -1
  52. package/package.json +4 -3
package/README.md CHANGED
@@ -106,6 +106,7 @@ Short version, one line each. The depth is in the linked pages.
106
106
  | `/undo` | Reverts what the last turn changed |
107
107
  | `/update` | Installs the newest version and reopens on this conversation |
108
108
  | `/mcp` | Manages connected MCP servers |
109
+ | `/feedback` | Sends the maintainer a message, no account needed |
109
110
  | `shift-tab` | Cycles interaction modes |
110
111
 
111
112
  Type while it works and your message queues; press up to take it back and edit it.
package/dist/cli/App.js CHANGED
@@ -35,7 +35,8 @@ import { appendForbidden, appendForbiddenCommand } from "../governor/write.js";
35
35
  import { addRoot, removeRoot } from "../tools/workspace.js";
36
36
  import { discoverRelatedRoots } from "../tools/workspaceDiscover.js";
37
37
  import { rootLabel, rootsOf, relativize } from "../tools/paths.js";
38
- import { APPROVAL_DISMISSED, APPROVAL_TEXT } from "../tools/approval.js";
38
+ import { APPROVAL_DISMISSED, APPROVAL_TEXT, readFreeText } from "../tools/approval.js";
39
+ import { buildFeedback, previewOf, refuseReason, sendFeedback, withAddition } from "./feedback.js";
39
40
  import { KeySetup } from "./components/KeySetup.js";
40
41
  import { setupView } from "./keySetup.js";
41
42
  import { KeyManager } from "./components/KeyManager.js";
@@ -1432,7 +1433,7 @@ export function App({ resumeSessionId, initialScreen }) {
1432
1433
  /**
1433
1434
  * Write a server's config and connect it live — shared by the typed `/mcp add`, the
1434
1435
  * `/mcp` box's Add and Edit, and (indirectly, through the same writer) the
1435
- * `add_mcp_server` tool. One path so a config any of them accepts is one the others
1436
+ * `mcp_server` tool. One path so a config any of them accepts is one the others
1436
1437
  * would too. Connects immediately: writing the file and telling the user to restart
1437
1438
  * would defeat the entire point of a guided add.
1438
1439
  */
@@ -1481,7 +1482,7 @@ export function App({ resumeSessionId, initialScreen }) {
1481
1482
  /**
1482
1483
  * `/mcp add <name> <command|url> [args…]` and `/mcp remove <name>`.
1483
1484
  *
1484
- * Shares its parser and writer with the `add_mcp_server` tool, so a config the command
1485
+ * Shares its parser and writer with the `mcp_server` tool, so a config the command
1485
1486
  * accepts is exactly one the tool would, and vice versa.
1486
1487
  */
1487
1488
  async function mcpConfigCommand(arg) {
@@ -2320,7 +2321,7 @@ export function App({ resumeSessionId, initialScreen }) {
2320
2321
  }
2321
2322
  // Hand a free-text directive to the model with an instruction wrapper, as its own
2322
2323
  // turn — used by the manual /rules and /skills commands (the model does the
2323
- // "rewrite it well and save it" work via remember_rule / create_skill).
2324
+ // "rewrite it well and save it" work via remember_rule / the skill tool).
2324
2325
  async function runDirective(instruction, activity) {
2325
2326
  const s = session.current;
2326
2327
  if (!s)
@@ -2422,6 +2423,41 @@ export function App({ resumeSessionId, initialScreen }) {
2422
2423
  }
2423
2424
  // /analytics — the anonymous usage ping. Bare opens the on/off switch, the same
2424
2425
  // fixed box every other setting uses; an argument acts directly, same as /model.
2426
+ // /feedback — a message to the maintainer, from inside the app. No account, no issue
2427
+ // tracker, no mail client: the whole point is that it costs the sender nothing. What
2428
+ // leaves the machine is decided in cli/feedback.ts and shown here before it goes.
2429
+ if (name === "/feedback") {
2430
+ const typed = arg.trim();
2431
+ const message = typed || (await askApproval.current("What would you like to tell the maintainer?", ["Cancel"], undefined, undefined, { label: "Your message", placeholder: "what is missing, broken, or worth adding" }).then((answer) => readFreeText(answer) ?? ""));
2432
+ if (!message.trim())
2433
+ return;
2434
+ // The confirm LOOPS, because the moment you read your own message back is the
2435
+ // moment you remember the thing you left out — usually an email address to reply
2436
+ // to. Typing in the box's own text row adds a line and shows the message again,
2437
+ // rather than cancelling and retyping the whole thing.
2438
+ let text = message;
2439
+ for (;;) {
2440
+ const refusal = refuseReason(text);
2441
+ if (refusal)
2442
+ return say(refusal);
2443
+ const feedback = buildFeedback(text, appVersion());
2444
+ const choice = await askApproval.current(previewOf(feedback), ["Send it", "Don't send"], undefined, undefined, {
2445
+ label: "add a line",
2446
+ placeholder: "your email for a reply, or more detail",
2447
+ });
2448
+ const added = readFreeText(choice);
2449
+ if (added !== null) {
2450
+ text = withAddition(text, added);
2451
+ continue;
2452
+ }
2453
+ if (choice !== "Send it")
2454
+ return note("Not sent.");
2455
+ note("sending…");
2456
+ const result = await sendFeedback(feedback);
2457
+ note(result.message, result.ok ? undefined : { error: true });
2458
+ return;
2459
+ }
2460
+ }
2425
2461
  if (name === "/analytics") {
2426
2462
  const verb = arg.trim().toLowerCase();
2427
2463
  if (verb === "on" || verb === "off") {
@@ -2674,7 +2710,7 @@ export function App({ resumeSessionId, initialScreen }) {
2674
2710
  // `/model openrouter` alone: that provider's picker.
2675
2711
  if (!words)
2676
2712
  return setOverlay({ kind: "model", providerId });
2677
- const picked = providerId === current ? here : resolveChoice(words, orderedModelsOf(providerId), "model");
2713
+ const picked = providerId === current && words === arg.trim() ? here : resolveChoice(words, orderedModelsOf(providerId), "model");
2678
2714
  if (picked.kind === "error")
2679
2715
  return say(picked.message);
2680
2716
  // Several fit: show exactly those, in the picker, rather than a list to retype from.
@@ -2862,7 +2898,7 @@ export function App({ resumeSessionId, initialScreen }) {
2862
2898
  if (name === "/skills") {
2863
2899
  if (arg) {
2864
2900
  await runDirective(`The user wants a new reusable skill for this project: "${arg}". Design it and save it ` +
2865
- `with create_skill — a short invocation name, a one-line description, and the procedure ` +
2901
+ `with the skill tool — a short invocation name, a one-line description, and the procedure ` +
2866
2902
  `as a clear markdown checklist (use $ARGUMENTS/$1 if it should take input). Then confirm.`, "creating a skill…");
2867
2903
  return;
2868
2904
  }
@@ -3151,9 +3187,12 @@ export function App({ resumeSessionId, initialScreen }) {
3151
3187
  return {
3152
3188
  label: m.label + (m.id === id ? " ✓" : ""),
3153
3189
  description: m.description ? `${facts} · ${m.description}` : facts,
3190
+ // Searched but not shown, so a filter opened by `/model <words>` matches the same
3191
+ // things the words matched: the id as well as the name.
3192
+ keywords: m.id,
3154
3193
  };
3155
3194
  });
3156
- return (_jsx(Picker, { title: `Choose a ${pickerProvider} model`, items: items, width: width, maxRows: maxRows, initialIndex: Math.max(0, models.findIndex((m) => m.id === id)), initialFilter: overlay.filter, onSelect: onOverlaySelect, onCancel: onOverlayCancel }));
3195
+ return (_jsx(Picker, { title: `Choose ${/^[aeiou]/i.test(pickerProvider) ? "an" : "a"} ${pickerProvider} model`, items: items, width: width, maxRows: maxRows, initialIndex: Math.max(0, models.findIndex((m) => m.id === id)), initialFilter: overlay.filter, onSelect: onOverlaySelect, onCancel: onOverlayCancel }));
3157
3196
  }
3158
3197
  if (overlay.kind === "think") {
3159
3198
  const model = cur?.modelConfig.model ?? DEFAULT_MODEL_CONFIG.model;