@mulmoclaude/mulmoscript-plugin 4.0.0 → 4.1.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.
package/dist/vue.cjs CHANGED
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_plugin = require("./plugin-BLp8tSYt.cjs");
6
- const require_contract = require("./contract-DxKVCRQk.cjs");
6
+ const require_contract = require("./contract-BhN3yKJC.cjs");
7
7
  let _mulmocast_types = require("@mulmocast/types");
8
8
  let vue = require("vue");
9
9
  let _mulmocast_beat_editor = require("@mulmocast/beat-editor");
@@ -213,6 +213,15 @@ var GENERATION_EVENT_KINDS = /* @__PURE__ */ new Set([
213
213
  "movie",
214
214
  "pdf"
215
215
  ]);
216
+ function parseScriptChangedEvent(payload) {
217
+ if (!isRecord(payload)) return null;
218
+ const { filePath, origin } = payload;
219
+ if (typeof filePath !== "string") return null;
220
+ return {
221
+ filePath,
222
+ ...typeof origin === "string" ? { origin } : {}
223
+ };
224
+ }
216
225
  function parseGenerationEvent(payload) {
217
226
  if (!isRecord(payload)) return null;
218
227
  const { kind, filePath, key, done, error } = payload;
@@ -259,9 +268,25 @@ function useMulmoScriptTransport() {
259
268
  handler(event);
260
269
  });
261
270
  }
271
+ /**
272
+ * A write to this script landed — reload from disk.
273
+ *
274
+ * `ownOrigin` is this View's id. Its own writes echo back on the same channel, and acting
275
+ * on them would rebuild the element the caret is in on every keystroke, so they are dropped
276
+ * here. A write from the agent carries no origin and always reaches the handler.
277
+ */
278
+ function onScriptChanged(filePath, ownOrigin, handler) {
279
+ return runtime.pubsub.subscribe(require_contract.SCRIPT_CHANGED_EVENT, (payload) => {
280
+ const event = parseScriptChangedEvent(payload);
281
+ if (!event) return;
282
+ if (!require_contract.shouldReloadForScriptChange(event, filePath(), ownOrigin)) return;
283
+ handler();
284
+ });
285
+ }
262
286
  return {
263
287
  call,
264
- onGenerationEvent
288
+ onGenerationEvent,
289
+ onScriptChanged
265
290
  };
266
291
  }
267
292
  //#endregion
@@ -555,6 +580,17 @@ function useCharacterImages({ api, filePath, chatSessionId, getImages }) {
555
580
  //#endregion
556
581
  //#region src/vue/composables/useDeckEditor.ts
557
582
  var DECK_SAVE_DEBOUNCE_MS = 300;
583
+ /**
584
+ * Who this editor is, on the wire.
585
+ *
586
+ * Every write carries it so the server's "this script changed" broadcast can be told apart
587
+ * from someone else's. Without it a save would echo back and reload the editor mid-keystroke,
588
+ * rebuilding the element the caret sits in.
589
+ *
590
+ * Per module instance rather than per component: one View is mounted at a time, and a value
591
+ * that survives a remount keeps a save in flight from being mistaken for a foreign write.
592
+ */
593
+ var EDITOR_ORIGIN = `deck-editor-${Math.random().toString(36).slice(2)}`;
558
594
  function useDeckEditor({ api, filePath, effectiveScript, commitScript }) {
559
595
  const isDeck = (0, vue.computed)(() => isAllSlideDeck(effectiveScript.value));
560
596
  const deckScriptInput = (0, vue.computed)(() => effectiveScript.value);
@@ -574,7 +610,8 @@ function useDeckEditor({ api, filePath, effectiveScript, commitScript }) {
574
610
  if (!next || !filePath.value) return;
575
611
  const response = await api.call("updateScript", {
576
612
  filePath: filePath.value,
577
- script: next
613
+ script: next,
614
+ origin: EDITOR_ORIGIN
578
615
  });
579
616
  if (!response.ok) {
580
617
  console.error("[presentMulmoScript] deck save failed:", response.error);
@@ -591,11 +628,25 @@ function useDeckEditor({ api, filePath, effectiveScript, commitScript }) {
591
628
  flushDeckSave();
592
629
  }
593
630
  }
631
+ /**
632
+ * Reload when someone else writes this script — the agent, or another window.
633
+ *
634
+ * A pending local edit is flushed first rather than dropped: the user's keystrokes are the
635
+ * thing they would notice losing, and the write that triggered this has already landed, so
636
+ * flushing cannot clobber it out of order.
637
+ */
638
+ function watchForeignWrites(reload) {
639
+ return api.onScriptChanged(() => filePath.value, EDITOR_ORIGIN, () => {
640
+ flushPendingDeckSave();
641
+ reload();
642
+ });
643
+ }
594
644
  return {
595
645
  isDeck,
596
646
  deckScriptInput,
597
647
  onDeckUpdate,
598
- flushPendingDeckSave
648
+ flushPendingDeckSave,
649
+ watchForeignWrites
599
650
  };
600
651
  }
601
652
  /** Reactive message bundle for the active host locale. The plugin carries its
@@ -1538,12 +1589,15 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
1538
1589
  }
1539
1590
  });
1540
1591
  }
1541
- const { isDeck, deckScriptInput, onDeckUpdate, flushPendingDeckSave } = useDeckEditor({
1592
+ const { isDeck, deckScriptInput, onDeckUpdate, flushPendingDeckSave, watchForeignWrites } = useDeckEditor({
1542
1593
  api,
1543
1594
  filePath,
1544
1595
  effectiveScript,
1545
1596
  commitScript
1546
1597
  });
1598
+ const unsubscribeForeignWrites = watchForeignWrites(() => {
1599
+ refreshScriptFromDisk();
1600
+ });
1547
1601
  const deckBeats = (0, vue.computed)(() => (0, _mulmocast_beat_editor.beatsOf)(deckScriptInput.value));
1548
1602
  function onDeckBeatsUpdate(beats) {
1549
1603
  onDeckUpdate((0, _mulmocast_beat_editor.withBeats)(deckScriptInput.value, beats));
@@ -1552,6 +1606,7 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
1552
1606
  flushPendingDeckSave();
1553
1607
  resetBeatMovies();
1554
1608
  unsubscribeGenerationEvents();
1609
+ unsubscribeForeignWrites();
1555
1610
  });
1556
1611
  const loadedSource = (0, vue.ref)("");
1557
1612
  const sourceChanged = (0, vue.computed)(() => editableSource.value !== loadedSource.value);
@@ -2229,7 +2284,7 @@ var _plugin_vue_export_helper_default = (sfc, props) => {
2229
2284
  };
2230
2285
  //#endregion
2231
2286
  //#region src/vue/View.vue
2232
- var View_default = /*#__PURE__*/ _plugin_vue_export_helper_default(View_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-222045a6"]]);
2287
+ var View_default = /*#__PURE__*/ _plugin_vue_export_helper_default(View_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-87bf6e4c"]]);
2233
2288
  //#endregion
2234
2289
  //#region src/vue/Preview.vue?vue&type=script&setup=true&lang.ts
2235
2290
  var _hoisted_1 = {