mulmoclaude 1.2.0 → 1.4.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 (96) hide show
  1. package/README.md +1 -1
  2. package/client/assets/{PluginScopedRoot-CjiZ2FJI.js → PluginScopedRoot-DYk4nRpW.js} +1 -1
  3. package/client/assets/index-7QnbsZZr.css +2 -0
  4. package/client/assets/{index-yQkLdtMk.js → index-C3SRVT2p.js} +84 -85
  5. package/client/assets/{marp-Bs_qwoKZ.js → marp-DxctLEy1.js} +12 -3
  6. package/client/index.html +3 -3
  7. package/package.json +7 -6
  8. package/server/agent/attachmentConverter.ts +0 -25
  9. package/server/agent/mcp-server.ts +27 -8
  10. package/server/api/auth/viewToken.ts +16 -8
  11. package/server/api/routes/agent.ts +49 -11
  12. package/server/api/routes/collections.ts +274 -102
  13. package/server/api/routes/files.ts +57 -54
  14. package/server/api/routes/mulmo-script.ts +257 -895
  15. package/server/api/routes/wiki/history.ts +17 -19
  16. package/server/build/dispatcher.mjs +2 -2
  17. package/server/events/collection-change.ts +1 -5
  18. package/server/events/file-change.ts +1 -6
  19. package/server/events/pub-sub/index.ts +15 -2
  20. package/server/events/relay-client.ts +6 -1
  21. package/server/events/session-store/index.ts +11 -2
  22. package/server/index.ts +51 -78
  23. package/server/plugins/diagnostics.ts +0 -6
  24. package/server/plugins/mulmoscript-server.ts +58 -0
  25. package/server/prompts/system/system.md +2 -3
  26. package/server/remoteHost/handlers/getCollection.ts +5 -4
  27. package/server/remoteHost/handlers/getFeed.ts +10 -5
  28. package/server/remoteHost/handlers/googleCalendar.ts +50 -3
  29. package/server/remoteHost/handlers/index.ts +3 -1
  30. package/server/services/translation/index.ts +10 -3
  31. package/server/utils/errors.ts +7 -21
  32. package/server/utils/files/html-store.ts +2 -16
  33. package/server/utils/files/journal-io.ts +0 -12
  34. package/server/utils/files/plugins-io.ts +2 -11
  35. package/server/utils/files/safe.ts +39 -0
  36. package/server/utils/httpError.ts +6 -0
  37. package/server/utils/text.ts +7 -23
  38. package/server/utils/time.ts +0 -3
  39. package/server/workspace/collections/index.ts +6 -4
  40. package/server/workspace/collections/remoteView.ts +31 -22
  41. package/server/workspace/collections/watcher.ts +1 -0
  42. package/server/workspace/custom-dirs.ts +16 -6
  43. package/server/workspace/journal/state.ts +1 -9
  44. package/server/workspace/memory/topic-index-hook.ts +0 -9
  45. package/server/workspace/memory/topic-io.ts +0 -4
  46. package/server/workspace/reference-dirs.ts +8 -3
  47. package/server/workspace/skills/external/catalog.ts +24 -13
  48. package/server/workspace/skills/writer.ts +20 -16
  49. package/server/workspace/wiki-pages/snapshot.ts +13 -12
  50. package/src/components/SettingsGoogleTab.vue +4 -1
  51. package/src/components/StackView.vue +12 -1
  52. package/src/composables/collections/uiHost.ts +2 -1
  53. package/src/composables/useChatScroll.ts +18 -6
  54. package/src/composables/useFileDropZone.ts +3 -15
  55. package/src/composables/useFileSelection.ts +4 -1
  56. package/src/composables/useStickToBottom.ts +51 -0
  57. package/src/config/apiRoutes.ts +20 -0
  58. package/src/config/roles.ts +0 -4
  59. package/src/lang/de.ts +0 -30
  60. package/src/lang/en.ts +0 -30
  61. package/src/lang/es.ts +0 -30
  62. package/src/lang/fr.ts +0 -30
  63. package/src/lang/ja.ts +0 -30
  64. package/src/lang/ko.ts +0 -30
  65. package/src/lang/pt-BR.ts +0 -30
  66. package/src/lang/zh.ts +0 -30
  67. package/src/plugins/accounting/index.ts +0 -2
  68. package/src/plugins/api.ts +0 -6
  69. package/src/plugins/canvas/index.ts +0 -2
  70. package/src/plugins/chart/index.ts +0 -2
  71. package/src/plugins/editImages/index.ts +0 -2
  72. package/src/plugins/generateImage/index.ts +0 -2
  73. package/src/plugins/manageSkills/index.ts +0 -2
  74. package/src/plugins/markdown/index.ts +0 -2
  75. package/src/plugins/photoLocations/index.ts +0 -2
  76. package/src/plugins/presentCollection/index.ts +0 -2
  77. package/src/plugins/presentForm/index.ts +0 -2
  78. package/src/plugins/presentHtml/index.ts +0 -2
  79. package/src/plugins/presentMulmoScript/definition.ts +11 -116
  80. package/src/plugins/presentMulmoScript/index.ts +62 -12
  81. package/src/plugins/presentSVG/index.ts +0 -2
  82. package/src/plugins/skill/index.ts +0 -3
  83. package/src/plugins/spreadsheet/engine/parser.ts +0 -103
  84. package/src/plugins/spreadsheet/index.ts +0 -2
  85. package/src/plugins/textResponse/index.ts +0 -3
  86. package/src/plugins/wiki/index.ts +0 -2
  87. package/src/types/notification.ts +0 -10
  88. package/src/utils/api.ts +0 -4
  89. package/src/utils/dom/scrollable.ts +15 -0
  90. package/src/utils/errors.ts +7 -38
  91. package/client/assets/index-D5nJbMO1.css +0 -2
  92. package/server/api/routes/mulmoScriptValidate.ts +0 -101
  93. package/server/utils/mulmoErrorCapture.ts +0 -93
  94. package/src/plugins/presentMulmoScript/Preview.vue +0 -23
  95. package/src/plugins/presentMulmoScript/View.vue +0 -1949
  96. package/src/plugins/presentMulmoScript/helpers.ts +0 -206
@@ -328,10 +328,10 @@ async function persistUserTurn(params: StartChatParams, ctx: { isFirstTurn: bool
328
328
  return validOrigin;
329
329
  }
330
330
 
331
- // Build the LLM-bound message (journal pointer + attached-file
332
- // markers) and kick off the detached background agent run. The
333
- // background run itself is fire-and-forget; this awaits only the
334
- // claudeSessionId read that must precede it.
331
+ // Build the LLM-bound message (see decorateMessageForCli) and kick
332
+ // off the detached background agent run. The background run itself is
333
+ // fire-and-forget; this awaits only the claudeSessionId read that must
334
+ // precede it (its presence decides whether the journal pointer is added).
335
335
  async function dispatchAgentRun(
336
336
  params: StartChatParams,
337
337
  ctx: { extras: RequestExtras; resultsFilePath: string; abortController: AbortController; validOrigin: SessionOrigin | undefined },
@@ -350,9 +350,26 @@ async function dispatchAgentRun(
350
350
  resumed: Boolean(claudeSessionId),
351
351
  });
352
352
 
353
- const baseMessage = claudeSessionId ? message : prependJournalPointer(message, workspacePath);
354
- const decoratedMessage = withAttachedFileMarker(baseMessage, extras.attachedFilePaths);
353
+ const decoratedMessage = decorateMessageForCli({
354
+ message,
355
+ workspaceDir: workspacePath,
356
+ attachedFilePaths: extras.attachedFilePaths,
357
+ resumed: Boolean(claudeSessionId),
358
+ });
355
359
 
360
+ // Deliberately not awaited — the request returns the SSE stream immediately
361
+ // and the run continues past it. The terminal `.catch` is the safety net for
362
+ // anything its own try/catch/finally misses; a bare `void` would only hide
363
+ // such a failure from the linter, not from the process.
364
+ //
365
+ // BEHAVIOUR NOTE, revisit if the supervisor story changes: before this
366
+ // `.catch` existed, a rejection escaping `runAgentInBackground` reached the
367
+ // process-level `unhandledRejection` handler in server/index.ts, which logs
368
+ // and `process.exit(1)` — one failed background run bounced the whole
369
+ // server, taking every other session's SSE stream with it. Catching keeps
370
+ // those sessions alive, at the cost of staying up after a failure a
371
+ // supervisor restart would have cleared. To return to fail-fast, rethrow
372
+ // from the handler.
356
373
  runAgentInBackground({
357
374
  decoratedMessage,
358
375
  role,
@@ -365,7 +382,7 @@ async function dispatchAgentRun(
365
382
  attachments: extras.attachments,
366
383
  userTimezone,
367
384
  origin: validOrigin,
368
- });
385
+ }).catch(logBackgroundError("agent", "background agent run failed"));
369
386
  }
370
387
 
371
388
  interface RequestExtras {
@@ -577,7 +594,9 @@ async function loadImageFromPath(value: string, declaredMimeType: string | undef
577
594
  // CodeRabbit review on #1045.
578
595
  const UNSAFE_MARKER_CHARS_RE = /[\r\n\]]/;
579
596
 
580
- /** Marker prepended to the LLM-bound user message that tells the
597
+ type MarkerPosition = "prepend" | "append";
598
+
599
+ /** Marker attached to the LLM-bound user message that tells the
581
600
  * model which workspace files are attached / selected for this turn.
582
601
  * One `[Attached file: <path>]` line is emitted per path so multi-
583
602
  * file flows (e.g. paste one image + pick another → "combine these")
@@ -585,12 +604,31 @@ const UNSAFE_MARKER_CHARS_RE = /[\r\n\]]/;
585
604
  * full list in `imagePaths`. The user's persisted (jsonl) and
586
605
  * broadcast (UI) message is the raw text — these marker lines are
587
606
  * added strictly on the path to Claude. The system prompt teaches
588
- * the model how to interpret them. */
589
- export function withAttachedFileMarker(message: string, attachedFilePaths: string[]): string {
607
+ * the model how to interpret them.
608
+ *
609
+ * `position` defaults to `"prepend"`; a command turn passes `"append"`
610
+ * so the leading `/` stays at position 0 (see `decorateMessageForCli`). */
611
+ export function withAttachedFileMarker(message: string, attachedFilePaths: string[], position: MarkerPosition = "prepend"): string {
590
612
  const safePaths = attachedFilePaths.filter((relPath) => !UNSAFE_MARKER_CHARS_RE.test(relPath));
591
613
  if (safePaths.length === 0) return message;
592
614
  const markerLines = safePaths.map((relPath) => `[Attached file: ${relPath}]`).join("\n");
593
- return `${markerLines}\n\n${message}`;
615
+ return position === "append" ? `${message}\n\n${markerLines}` : `${markerLines}\n\n${message}`;
616
+ }
617
+
618
+ /** Build the CLI-bound message, preserving a leading `/` as the CLI's
619
+ * deterministic slash-command trigger. The CLI resolves a slash command
620
+ * only when the message STARTS with `/name`; any decoration pushed in
621
+ * front of it silently drops skill selection back to the model guessing
622
+ * from descriptions (#2134). A slash-first message is a command, not an
623
+ * open question — so skip the journal pointer (prior-session context is
624
+ * irrelevant to a command) and append the file markers after the body
625
+ * instead of prepending. Detection is position-0 `startsWith` to match
626
+ * the CLI; the collection UI and manual entry emit no leading whitespace. */
627
+ export function decorateMessageForCli(args: { message: string; workspaceDir: string; attachedFilePaths: string[]; resumed: boolean }): string {
628
+ const { message, workspaceDir, attachedFilePaths, resumed } = args;
629
+ const isCommand = message.startsWith("/");
630
+ const base = resumed || isCommand ? message : prependJournalPointer(message, workspaceDir);
631
+ return withAttachedFileMarker(base, attachedFilePaths, isCommand ? "append" : "prepend");
594
632
  }
595
633
 
596
634
  // ── HTTP route ──────────────────────────────────────────────────────