@mulmoclaude/core 1.6.0 → 1.7.1

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 (63) hide show
  1. package/assets/helps/error-recovery.md +46 -0
  2. package/assets/helps/google-calendar-collection.md +57 -3
  3. package/assets/helps/google.md +3 -2
  4. package/dist/calendarGrid-CaS9er8i.cjs +576 -0
  5. package/dist/calendarGrid-CaS9er8i.cjs.map +1 -0
  6. package/dist/calendarGrid-CrGxeCOG.js +397 -0
  7. package/dist/calendarGrid-CrGxeCOG.js.map +1 -0
  8. package/dist/collection/index.cjs +44 -44
  9. package/dist/collection/index.cjs.map +1 -1
  10. package/dist/collection/index.js +2 -2
  11. package/dist/collection/registry/server/index.cjs +2 -2
  12. package/dist/collection/registry/server/index.js +2 -2
  13. package/dist/collection/server/index.cjs +4 -4
  14. package/dist/collection/server/index.js +3 -3
  15. package/dist/collection-watchers/index.cjs +5 -5
  16. package/dist/collection-watchers/index.cjs.map +1 -1
  17. package/dist/collection-watchers/index.js +4 -4
  18. package/dist/{discovery--kRUWed0.cjs → discovery-DYcR83qx.cjs} +64 -53
  19. package/dist/discovery-DYcR83qx.cjs.map +1 -0
  20. package/dist/{discovery-CKR4TOX3.js → discovery-_fjsluLx.js} +43 -32
  21. package/dist/discovery-_fjsluLx.js.map +1 -0
  22. package/dist/feeds/index.cjs +4 -4
  23. package/dist/feeds/index.js +2 -2
  24. package/dist/feeds/server/index.cjs +6 -6
  25. package/dist/feeds/server/index.js +4 -4
  26. package/dist/google/apiClient.d.ts +6 -0
  27. package/dist/google/calendar.d.ts +79 -8
  28. package/dist/google/calendarPushState.d.ts +17 -0
  29. package/dist/google/collectionPush.d.ts +64 -0
  30. package/dist/google/collectionSync.d.ts +10 -0
  31. package/dist/google/index.cjs +712 -36
  32. package/dist/google/index.cjs.map +1 -1
  33. package/dist/google/index.d.ts +7 -3
  34. package/dist/google/index.js +683 -37
  35. package/dist/google/index.js.map +1 -1
  36. package/dist/google/pushDateTime.d.ts +10 -0
  37. package/dist/google/pushPlan.d.ts +73 -0
  38. package/dist/{ingestTypes-xX8VpQqh.cjs → ingestTypes-D1GQdG8e.cjs} +3 -3
  39. package/dist/{ingestTypes-xX8VpQqh.cjs.map → ingestTypes-D1GQdG8e.cjs.map} +1 -1
  40. package/dist/{ingestTypes-L59cIGgX.js → ingestTypes-XReG-li7.js} +2 -2
  41. package/dist/{ingestTypes-L59cIGgX.js.map → ingestTypes-XReG-li7.js.map} +1 -1
  42. package/dist/{promptSafety-CQ5Un4wi.js → promptSafety-C--op_6a.js} +3 -269
  43. package/dist/promptSafety-C--op_6a.js.map +1 -0
  44. package/dist/{promptSafety-DfZYNtjK.cjs → promptSafety-FD8cQn3e.cjs} +8 -358
  45. package/dist/promptSafety-FD8cQn3e.cjs.map +1 -0
  46. package/dist/remote-host/index.cjs +8 -0
  47. package/dist/remote-host/index.cjs.map +1 -1
  48. package/dist/remote-host/index.d.ts +21 -0
  49. package/dist/remote-host/index.js +8 -1
  50. package/dist/remote-host/index.js.map +1 -1
  51. package/dist/{server-D_6FLygK.js → server-BlIrtGKl.js} +4 -4
  52. package/dist/{server-D_6FLygK.js.map → server-BlIrtGKl.js.map} +1 -1
  53. package/dist/{server-gEOeV_Nv.cjs → server-l4TZ5Lbf.cjs} +21 -21
  54. package/dist/{server-gEOeV_Nv.cjs.map → server-l4TZ5Lbf.cjs.map} +1 -1
  55. package/package.json +1 -1
  56. package/dist/discovery--kRUWed0.cjs.map +0 -1
  57. package/dist/discovery-CKR4TOX3.js.map +0 -1
  58. package/dist/ids-BnTh3Hl0.cjs +0 -226
  59. package/dist/ids-BnTh3Hl0.cjs.map +0 -1
  60. package/dist/ids-s4GfmE93.js +0 -131
  61. package/dist/ids-s4GfmE93.js.map +0 -1
  62. package/dist/promptSafety-CQ5Un4wi.js.map +0 -1
  63. package/dist/promptSafety-DfZYNtjK.cjs.map +0 -1
@@ -623,3 +623,49 @@ queue of paths, with one short-delay retry on 429. See the throttled-resolver
623
623
  example in `custom-view.md` ("Displaying images"). Do NOT widen the server
624
624
  cap, switch to base64-embedding images in the HTML, or treat the 429'd paths
625
625
  as bad values.
626
+
627
+ ## An API key in `.env` has no effect — the shell is shadowing it
628
+
629
+ ### Symptoms
630
+
631
+ - The user says they put a key (`GEMINI_API_KEY`, `OPENAI_API_KEY`, …) in
632
+ `.env` and restarted, but generation still fails with an auth / 401 /
633
+ "API key not valid" error from the provider.
634
+ - They may have edited `.env` several times, each time with no change.
635
+ - The bell may show **"Shell env is overriding .env"**, and the server log
636
+ a `[shadowed-env]` warning naming the keys.
637
+
638
+ ### Cause
639
+
640
+ An exported shell variable beats the file. `.env` is loaded with
641
+ no-override semantics, so if `~/.zshrc` (or the current shell) still holds
642
+ `export GEMINI_API_KEY=<old value>`, the file's value is read and
643
+ discarded. Editing `.env` cannot fix it, which is why the loop repeats.
644
+
645
+ An **empty** export shadows just as hard: `export GEMINI_API_KEY=` counts
646
+ as set, so the provider receives an empty key while a perfectly good one
647
+ sits in `.env`.
648
+
649
+ Two files can be shadowed this way — the directory the user launched from
650
+ (`npx mulmoclaude`) and the server's own working directory (`yarn dev`).
651
+
652
+ ### Fix
653
+
654
+ Have the user check the shell, not the file. Test whether the variable
655
+ is **set**, not whether it prints something — `export GEMINI_API_KEY=`
656
+ prints nothing and still shadows, which is the case `echo` cannot see:
657
+
658
+ ```bash
659
+ [ -n "${GEMINI_API_KEY+x}" ] && echo "set in the shell — this is what the app uses" \
660
+ || echo "not set — the shell is not the problem"
661
+ ```
662
+
663
+ If it reports "set", that shell value is what the app is using, whatever
664
+ `.env` says. Either correct the export, or remove it — from the current
665
+ shell AND from `~/.zshrc` / `~/.bashrc`, or the next terminal brings it
666
+ straight back — so the `.env` value takes effect. Restart the app
667
+ afterwards; the load happens once at boot.
668
+
669
+ Do NOT tell the user to re-check the spelling in `.env`, add the key
670
+ again, or move it elsewhere; the file is already correct, and it is being
671
+ read. The conflict is the whole problem.
@@ -6,10 +6,22 @@ events on a schedule and writes them as records — **without calling you**. No
6
6
  tool call, no tokens spent per sync, so hourly syncing is free.
7
7
 
8
8
  This is the mechanism for *keeping a collection fresh*. For one-off reads and
9
- for creating / editing / deleting events, use the `google` tool — see
9
+ for deleting events, use the `google` tool — see
10
10
  [The `google` tool](google.md). There is no bundled calendar collection: you
11
11
  author the schema when the user asks for one.
12
12
 
13
+ ## Both directions, but only one of them automatic
14
+
15
+ | Direction | How | When it runs |
16
+ | --- | --- | --- |
17
+ | Google → collection | the `googleCalendar` block | hourly, on creation, and on the **Sync** button |
18
+ | collection → Google | the **Push to Google** button in the collection view | only when the user clicks it |
19
+
20
+ There is no automatic write-back and no setting that enables one. If a user
21
+ asks for "two-way sync", tell them plainly: the pull is automatic, the push is
22
+ a button they press. Do not go looking for a config key for it — there isn't
23
+ one, and hunting for it is what makes this conversation go in circles.
24
+
13
25
  ## Requirements
14
26
 
15
27
  The user's Google account must be linked (`google` tool, `kind: "status"`). If
@@ -81,8 +93,50 @@ the calendar day view then draws each record as a proportional time block.
81
93
  records on that first pass.
82
94
 
83
95
  Records are ordinary collection records: the user can open, filter, and view
84
- them like any other. Edits they make locally are overwritten the next time
85
- Google reports a change to that event.
96
+ them like any other.
97
+
98
+ ## Pushing local work back — the Push to Google button
99
+
100
+ The collection view has a **Push to Google** button next to Sync. It creates
101
+ events for records added locally and updates events for records edited locally.
102
+
103
+ **Order matters, and this is the one thing to warn users about.** A pull
104
+ overwrites a locally edited record as soon as Google reports any change to that
105
+ event. So: push first, then sync. Syncing first can discard the edit that was
106
+ waiting to be pushed.
107
+
108
+ What the button does and deliberately does not do:
109
+
110
+ - **Creates** an event for a record that never came from a sync.
111
+ - **Updates** only the fields the user actually changed, so attendees,
112
+ reminders and recurrence rules stay untouched.
113
+ - **Never deletes.** A record deleted locally leaves its Google event alone —
114
+ a Google delete removes the event for every attendee and cannot be undone.
115
+ The count is reported so the user knows it was skipped; deleting for real is
116
+ the `google` tool's `calendarDeleteEvent`, after confirming with them.
117
+ - **Skips a record edited on both sides** and reports it, rather than picking a
118
+ winner. The user resolves it by editing one side to match.
119
+ - Pushes only `summary`, `start`, `end` and `colorId` — `htmlLink` and `status`
120
+ are read-only in Google, so a column mapped to either is ignored.
121
+
122
+ Reasons a record can be reported as skipped:
123
+
124
+ - **Its record id cannot be a Google event id.** Google requires 5-1024
125
+ characters from `0-9a-v`. Records created through the UI get a valid
126
+ generated id; a semantic id you authored (`team-standup`) cannot be used. Fix
127
+ by recreating the record without setting the primary field.
128
+ - **No `start` / `end` is mapped, on a record being CREATED.** An event cannot
129
+ be created without a span. Editing an existing event is unaffected — a changed
130
+ title or colour is patched on its own.
131
+ - **The calendar reports no timezone**, and the stored clock carries no offset
132
+ to fall back on.
133
+ - **Clearing an event colour** — Google has no way to unset one.
134
+
135
+ If the user only has `reader` access to the calendar, the whole push is refused
136
+ with that reason rather than failing event by event. A calendar the user can
137
+ reach by id but has not added to their calendar list has no role to check, so
138
+ the push goes ahead and reports Google's own refusal if the write turns out not
139
+ to be allowed — being unlisted is not treated as being read-only.
86
140
 
87
141
  ## Not for this
88
142
 
@@ -15,10 +15,11 @@ the original call — do not fall back to guessing.
15
15
  | --- | --- |
16
16
  | Read or change specific events / tasks / files, right now | this tool |
17
17
  | A collection that mirrors a calendar and keeps itself fresh | a `googleCalendar` block — see [Google Calendar sync](google-calendar-collection.md) |
18
+ | Records the user added/edited in a calendar collection to reach Google | the collection view's **Push to Google** button, not this tool |
18
19
 
19
20
  The collection route costs no tokens per refresh, so prefer it for anything
20
- recurring. Use this tool for one-off work and for everything the collection
21
- route cannot do (creating, editing and deleting).
21
+ recurring. Use this tool for one-off work, and for deleting — the push button
22
+ never deletes.
22
23
 
23
24
  ## Calendar
24
25