@mulmoclaude/core 4.9.0 → 4.9.2
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/assets/helps/bug-report-faq.md +12 -0
- package/assets/helps/error-recovery.md +144 -29
- package/assets/helps/sandbox.md +2 -2
- package/dist/collection/index.cjs +3 -2
- package/dist/collection/index.cjs.map +1 -1
- package/dist/collection/index.js +3 -2
- package/dist/collection/index.js.map +1 -1
- package/dist/collection/registry/server/index.cjs +3 -3
- package/dist/collection/registry/server/index.js +3 -3
- package/dist/collection/server/index.cjs +2 -2
- package/dist/collection/server/index.js +2 -2
- package/dist/collection-watchers/index.cjs +4 -4
- package/dist/collection-watchers/index.js +4 -4
- package/dist/{discovery-BY-nMCuh.js → discovery-BkIKvdh0.js} +3 -3
- package/dist/discovery-BkIKvdh0.js.map +1 -0
- package/dist/{discovery-2TvulIz8.cjs → discovery-tvFo-bUJ.cjs} +3 -3
- package/dist/discovery-tvFo-bUJ.cjs.map +1 -0
- package/dist/{dist-D8zokgGo.js → dist-BzoA9pDR.js} +6 -1
- package/dist/dist-BzoA9pDR.js.map +1 -0
- package/dist/{dist-CsgSfWwR.cjs → dist-Gj7ygaW2.cjs} +6 -1
- package/dist/dist-Gj7ygaW2.cjs.map +1 -0
- package/dist/errorMessage-BQNpSYdT.js +1 -0
- package/dist/errorMessage-CT-va_Pv.cjs +1 -0
- package/dist/errors-C7TI_t_4.js +10 -0
- package/dist/errors-C7TI_t_4.js.map +1 -0
- package/dist/errors-CdXsfFCF.cjs +15 -0
- package/dist/errors-CdXsfFCF.cjs.map +1 -0
- package/dist/feeds/server/index.cjs +4 -4
- package/dist/feeds/server/index.js +4 -4
- package/dist/google/index.cjs +3 -2
- package/dist/google/index.cjs.map +1 -1
- package/dist/google/index.js +3 -2
- package/dist/google/index.js.map +1 -1
- package/dist/{listen-UZA68Upt.cjs → listen-BXthb-9C.cjs} +2 -2
- package/dist/{listen-UZA68Upt.cjs.map → listen-BXthb-9C.cjs.map} +1 -1
- package/dist/{listen-D5av7GzB.js → listen-Dca-NoBi.js} +2 -2
- package/dist/{listen-D5av7GzB.js.map → listen-Dca-NoBi.js.map} +1 -1
- package/dist/notifier/index.cjs +1 -1
- package/dist/notifier/index.js +1 -1
- package/dist/notifier/types.d.ts +20 -11
- package/dist/{notifier-DZJj0sOh.cjs → notifier-B65Mvngb.cjs} +12 -7
- package/dist/notifier-B65Mvngb.cjs.map +1 -0
- package/dist/{notifier-DhnwR82U.js → notifier-vAp5t6wL.js} +12 -7
- package/dist/notifier-vAp5t6wL.js.map +1 -0
- package/dist/{promptSafety-Bte62OvU.js → promptSafety-BpBTh5xO.js} +2 -2
- package/dist/{promptSafety-Bte62OvU.js.map → promptSafety-BpBTh5xO.js.map} +1 -1
- package/dist/{promptSafety-Cv-SoTd4.cjs → promptSafety-caJWd1ZQ.cjs} +2 -2
- package/dist/{promptSafety-Cv-SoTd4.cjs.map → promptSafety-caJWd1ZQ.cjs.map} +1 -1
- package/dist/remote-host/index.cjs +1 -1
- package/dist/remote-host/index.js +1 -1
- package/dist/remote-host/server/index.cjs +4 -3
- package/dist/remote-host/server/index.cjs.map +1 -1
- package/dist/remote-host/server/index.js +4 -3
- package/dist/remote-host/server/index.js.map +1 -1
- package/dist/{remote-host-CFnl1I-L.js → remote-host-Cjox2F2J.js} +2 -2
- package/dist/{remote-host-CFnl1I-L.js.map → remote-host-Cjox2F2J.js.map} +1 -1
- package/dist/{remote-host-EQPlccB9.cjs → remote-host-DhAHBYzN.cjs} +2 -2
- package/dist/{remote-host-EQPlccB9.cjs.map → remote-host-DhAHBYzN.cjs.map} +1 -1
- package/dist/remote-view/index.cjs +1 -1
- package/dist/remote-view/index.js +1 -1
- package/dist/scheduler/index.cjs +2 -1
- package/dist/scheduler/index.cjs.map +1 -1
- package/dist/scheduler/index.js +2 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/{server-DXUt34Rt.cjs → server-Div1i_k5.cjs} +5 -4
- package/dist/{server-DXUt34Rt.cjs.map → server-Div1i_k5.cjs.map} +1 -1
- package/dist/{server-DyYwfNB6.js → server-Dk9x1VLG.js} +5 -4
- package/dist/{server-DyYwfNB6.js.map → server-Dk9x1VLG.js.map} +1 -1
- package/dist/utils/index.cjs +3 -10
- package/dist/utils/index.js +2 -9
- package/dist/whisper/index.cjs +2 -1
- package/dist/whisper/index.cjs.map +1 -1
- package/dist/whisper/index.js +2 -1
- package/dist/whisper/index.js.map +1 -1
- package/dist/wiki/index.cjs +1 -1
- package/dist/wiki/index.js +1 -1
- package/dist/workspace-setup/index.js +5 -0
- package/dist/workspace-setup/index.js.map +1 -1
- package/package.json +5 -5
- package/dist/discovery-2TvulIz8.cjs.map +0 -1
- package/dist/discovery-BY-nMCuh.js.map +0 -1
- package/dist/dist-CsgSfWwR.cjs.map +0 -1
- package/dist/dist-D8zokgGo.js.map +0 -1
- package/dist/notifier-DZJj0sOh.cjs.map +0 -1
- package/dist/notifier-DhnwR82U.js.map +0 -1
- package/dist/utils/index.cjs.map +0 -1
- package/dist/utils/index.js.map +0 -1
|
@@ -56,6 +56,18 @@ settings is the user's opt-in. The RemoteHost channel must also be connected —
|
|
|
56
56
|
what supplies the Firebase auth, so with the phone link down the send is a no-op by design. A user
|
|
57
57
|
who never connected a phone has nothing to receive the push regardless of the setting.
|
|
58
58
|
|
|
59
|
+
## MulmoClaude is answering with a different model than I expected
|
|
60
|
+
|
|
61
|
+
configKey: chatModel
|
|
62
|
+
source: server/agent/config.ts
|
|
63
|
+
|
|
64
|
+
Read `chatModel` from the live settings. Absent means MulmoClaude passes no `--model` at all and the
|
|
65
|
+
CLI resolves the model from `~/.claude/settings.json` — the same file the VS Code and Cursor Claude
|
|
66
|
+
Code extensions write their `/model` pick to, so a switch made in another editor changes MulmoClaude
|
|
67
|
+
too, with nothing on screen to say so. Setting the key from Settings → Model is what pins MulmoClaude
|
|
68
|
+
independently of that shared file. A session already running keeps its model until the next turn, so
|
|
69
|
+
"it changed partway through a conversation" is the expected shape of this, not a second bug.
|
|
70
|
+
|
|
59
71
|
## My chats never get titles or summaries
|
|
60
72
|
|
|
61
73
|
configKey: chatIndex
|
|
@@ -124,11 +124,17 @@ Report body:
|
|
|
124
124
|
|
|
125
125
|
```markdown
|
|
126
126
|
## What happened
|
|
127
|
+
|
|
127
128
|
## What I expected
|
|
129
|
+
|
|
128
130
|
## Steps to reproduce
|
|
131
|
+
|
|
129
132
|
1.
|
|
133
|
+
|
|
130
134
|
## Environment
|
|
135
|
+
|
|
131
136
|
(paste the diagnostics report here)
|
|
137
|
+
|
|
132
138
|
## Attachments
|
|
133
139
|
```
|
|
134
140
|
|
|
@@ -280,7 +286,7 @@ naming the file:
|
|
|
280
286
|
quotes, unquoted key.
|
|
281
287
|
- `role file does not match the role schema, skipping` — the `issues`
|
|
282
288
|
field names each field, e.g. `icon: Invalid input: expected string,
|
|
283
|
-
|
|
289
|
+
received undefined`. All of `id`, `name`, `icon`, `prompt`,
|
|
284
290
|
`availablePlugins` are required; `availablePlugins` must be an array
|
|
285
291
|
even for one entry.
|
|
286
292
|
- `role file is empty, skipping` — zero-length or whitespace only.
|
|
@@ -328,7 +334,7 @@ it:
|
|
|
328
334
|
`my role.json`, rejected as `Invalid role id 'my role'.` Neither name
|
|
329
335
|
reaches the role. Renaming is the only fix.
|
|
330
336
|
- `… the id is not a usable role id` — the reverse, e.g. `"id": "my
|
|
331
|
-
|
|
337
|
+
role"` in `designer.json`. `delete designer` still works, and renaming
|
|
332
338
|
to `my role.json` would take that away. Change the `id`.
|
|
333
339
|
- `… neither is a usable role id` — pick one id that matches the pattern
|
|
334
340
|
and use it for the file name and the `id` together.
|
|
@@ -543,9 +549,10 @@ user's file by re-encoding it.
|
|
|
543
549
|
A collection whose schema declares `storage: { type: "sqlite", path: … }`
|
|
544
550
|
keeps its records in a single SQLite database file, read/written through
|
|
545
551
|
Node's BUILT-IN `node:sqlite` module — no npm dependency. That module
|
|
546
|
-
exists only in **Node.js >= 22.5
|
|
547
|
-
|
|
548
|
-
|
|
552
|
+
exists only in **Node.js >= 22.5**. The app's own floor is >= 22.19, so a
|
|
553
|
+
supported runtime always has it and this failure means a Node built without
|
|
554
|
+
the module. Only sqlite-backed collections break (file and dataSource
|
|
555
|
+
collections keep working); every operation fails with
|
|
549
556
|
`sqlite storage needs the node:sqlite module (Node.js >= 22.5) — this
|
|
550
557
|
runtime cannot load it`.
|
|
551
558
|
|
|
@@ -926,12 +933,12 @@ They are genuinely different failures — a permanent load failure, a startup ra
|
|
|
926
933
|
and guessing between them is what makes this expensive. Since #2842 the log answers it directly,
|
|
927
934
|
so read these three before forming a theory:
|
|
928
935
|
|
|
929
|
-
| Log line
|
|
930
|
-
|
|
931
|
-
| `spawning agent … broker=tsx`
|
|
932
|
-
| `[mcp] broker ready bootMs=… initializeMs=…`
|
|
933
|
-
| `brokerEverReady=false reason=never-ready` on the retry warn
|
|
934
|
-
| `reason=ready-during-wait` on the retry warn
|
|
936
|
+
| Log line | What it tells you |
|
|
937
|
+
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
938
|
+
| `spawning agent … broker=tsx` | This install is on the SLOW path: the bundle is missing, so the broker is transcoded from source on every spawn (seconds to tens of seconds over a Windows/macOS bind mount). A `broker bundle missing` warn accompanies it once per process. |
|
|
939
|
+
| `[mcp] broker ready bootMs=… initializeMs=…` | The broker DID connect, and how long it took. `broker cold boot is slow` replaces it past 5 s. |
|
|
940
|
+
| `brokerEverReady=false reason=never-ready` on the retry warn | No beacon arrived for that chat, and the host kept looking until the beacon's own delivery budget was spent — the broker did not come up at all. The turn is NOT replayed: a replay would sit out another full connect wait and end in the same error. |
|
|
941
|
+
| `reason=ready-during-wait` on the retry warn | The beacon arrived while the host waited, so the broker lost the race by a moment and IS connected now. The turn is replayed, which is what fixes this one. |
|
|
935
942
|
| `brokerEverStarted=` on the `MCP tools were unavailable` warn | Whether the broker PROCESS ever existed, which is a different question from whether it answered. `true` with `brokerEverReady=false` means it launched and never finished booting — the boot is the problem (the mount, the `tsx` path). `false` means it never launched — the spawn is the problem. Diagnostic only, and not authenticated: under Docker everything needed to forge it sits in the per-session MCP config inside the workspace mount, so read it as evidence about a healthy install rather than as proof against a hostile one. |
|
|
936
943
|
|
|
937
944
|
### Fix
|
|
@@ -968,7 +975,7 @@ so read these three before forming a theory:
|
|
|
968
975
|
|
|
969
976
|
- The `google` tool (or a `google.calendar.*` remote command) fails with **"Google account not linked on this host"**.
|
|
970
977
|
- **"Google sign-in service unreachable"** or **"Google sign-in service returned HTTP …"**.
|
|
971
|
-
- **"multiple
|
|
978
|
+
- **"multiple client_secret\_*.json files found"**.
|
|
972
979
|
- **"Google Calendar API: HTTP 403"** with a hint about enabling the API.
|
|
973
980
|
- **"Google Calendar API: HTTP 403 — Request had insufficient authentication scopes"** when pushing
|
|
974
981
|
a collection to a calendar that is NOT in the account's own calendar list.
|
|
@@ -1121,8 +1128,7 @@ Pass the file instead. `putItems` accepts **`itemsFile`** — an absolute path t
|
|
|
1121
1128
|
a JSON file holding the array of record objects, read by the host:
|
|
1122
1129
|
|
|
1123
1130
|
```jsonc
|
|
1124
|
-
{ "action": "putItems", "slug": "slots", "mode": "create",
|
|
1125
|
-
"itemsFile": "/absolute/path/to/generated-slots.json" }
|
|
1131
|
+
{ "action": "putItems", "slug": "slots", "mode": "create", "itemsFile": "/absolute/path/to/generated-slots.json" }
|
|
1126
1132
|
```
|
|
1127
1133
|
|
|
1128
1134
|
Write the generated file **under the workspace**. Paths outside it are refused:
|
|
@@ -1144,17 +1150,17 @@ Rules that make it fail cleanly rather than silently:
|
|
|
1144
1150
|
|
|
1145
1151
|
Reading the refusal you got:
|
|
1146
1152
|
|
|
1147
|
-
| Message
|
|
1148
|
-
|
|
|
1149
|
-
| `must be an ABSOLUTE path`
|
|
1150
|
-
| `must be inside the workspace`
|
|
1151
|
-
| `is a symbolic link`
|
|
1152
|
-
| `changed while it was being opened`
|
|
1153
|
-
| `grew while it was being read`
|
|
1154
|
-
| `could not read \`itemsFile\``
|
|
1155
|
-
| `is not a regular file`
|
|
1156
|
-
| `could not be read as JSON`
|
|
1157
|
-
| `must hold a non-empty JSON array of record objects` | It parsed, but is `[]`, an object, or an array of scalars. The file must be `[{…}, {…}]` — the same row objects you would have passed as `items`.
|
|
1153
|
+
| Message | What it means |
|
|
1154
|
+
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1155
|
+
| `must be an ABSOLUTE path` | You passed a relative path. Pass the full one. |
|
|
1156
|
+
| `must be inside the workspace` | The file is outside the workspace (or a symlink out of it). Regenerate it under the workspace. |
|
|
1157
|
+
| `is a symbolic link` | Symlinks are never followed. Pass the real path. |
|
|
1158
|
+
| `changed while it was being opened` | The file was replaced mid-call. Finish writing it, then call putItems. |
|
|
1159
|
+
| `grew while it was being read` | The file was still being written. Wait for the script to finish, then call putItems. |
|
|
1160
|
+
| `could not read \`itemsFile\`` | The host cannot see that path — the usual cause is a file written to a temp dir outside the mount. Write it under the workspace. |
|
|
1161
|
+
| `is not a regular file` | The path is a directory, device, or fifo. |
|
|
1162
|
+
| `could not be read as JSON` | The file exists and was read, but does not parse. This is YOUR file's shape, not a host problem — check the script that wrote it (a truncated write, a trailing comma, log output mixed into the file). |
|
|
1163
|
+
| `must hold a non-empty JSON array of record objects` | It parsed, but is `[]`, an object, or an array of scalars. The file must be `[{…}, {…}]` — the same row objects you would have passed as `items`. |
|
|
1158
1164
|
|
|
1159
1165
|
Do NOT spawn the MCP bridge yourself. A hand-written JSON-RPC client fails
|
|
1160
1166
|
invisibly and can leave a partially written collection that nothing reports.
|
|
@@ -1196,10 +1202,14 @@ the calendar can place. So format the string, never convert it:
|
|
|
1196
1202
|
|
|
1197
1203
|
```js
|
|
1198
1204
|
// WRONG — appends `Z` and shifts the hours by the generating machine's offset
|
|
1199
|
-
{
|
|
1205
|
+
{
|
|
1206
|
+
startAt: new Date(`${day}T08:00`).toISOString();
|
|
1207
|
+
} // "2026-08-17T15:00:00.000Z"
|
|
1200
1208
|
|
|
1201
1209
|
// RIGHT — the clock you meant, written as the clock
|
|
1202
|
-
{
|
|
1210
|
+
{
|
|
1211
|
+
startAt: `${day}T08:00`;
|
|
1212
|
+
} // "2026-08-17T08:00"
|
|
1203
1213
|
```
|
|
1204
1214
|
|
|
1205
1215
|
The conversion is the more expensive half: had the format passed, a Tokyo court's
|
|
@@ -1249,7 +1259,7 @@ second line, with the plugin-load errors above it, is what a bug report needs.
|
|
|
1249
1259
|
### Symptoms
|
|
1250
1260
|
|
|
1251
1261
|
- Reading or writing a collection fails with `shared collection unavailable:
|
|
1252
|
-
|
|
1262
|
+
connect remote-host first`.
|
|
1253
1263
|
- A collection whose `schema.json` declares `"storage": { "type": "firestore" }`
|
|
1254
1264
|
never appears in the list at all.
|
|
1255
1265
|
- Reads and writes fail with `permission-denied` from Firestore even though the
|
|
@@ -1269,7 +1279,7 @@ The backend deliberately fails loudly instead of returning nothing.
|
|
|
1269
1279
|
|
|
1270
1280
|
2. **The collection never appears** — discovery REFUSED the schema, and the
|
|
1271
1281
|
reason is in the server log under `collections` (`schema.json rejected after
|
|
1272
|
-
|
|
1282
|
+
validation, skipping`). For a shared collection the usual reason is the app
|
|
1273
1283
|
declaration: `apps/{aid}/collections/{cid}/items` needs an `aid`, which comes
|
|
1274
1284
|
from `app.json` at the repository root, not from the schema.
|
|
1275
1285
|
|
|
@@ -1382,6 +1392,14 @@ treatment, and the workspace mounted if you want it to follow the port.
|
|
|
1382
1392
|
message.
|
|
1383
1393
|
- The platform token (bot token, app token) was revoked or regenerated.
|
|
1384
1394
|
- The bridge process is not running at all. Check before assuming anything above.
|
|
1395
|
+
Since #3084 a bridge that died says why on its last line — `[<transport>]
|
|
1396
|
+
unhandled rejection — exiting: …` or `[<transport>] uncaught exception —
|
|
1397
|
+
exiting: …`, naming the transport. A bridge stopped on purpose names the
|
|
1398
|
+
signal: Ctrl-C prints `[<transport>] SIGINT — shutting down`, while a plain
|
|
1399
|
+
`kill <pid>` sends SIGTERM and prints `[<transport>] SIGTERM — shutting down`.
|
|
1400
|
+
**No such line and the process gone** means either an older npm build (they
|
|
1401
|
+
had no handlers at all, so a missed `await` left only a stack trace) or a kill
|
|
1402
|
+
no handler can catch (`kill -9` / SIGKILL, or the OOM killer).
|
|
1385
1403
|
|
|
1386
1404
|
### What to collect if none of it explains the silence
|
|
1387
1405
|
|
|
@@ -1391,6 +1409,54 @@ the server's `[server] listening port=…` line, and whether
|
|
|
1391
1409
|
port, and did the bridge agree" — which is what every one of these turns out to
|
|
1392
1410
|
be.
|
|
1393
1411
|
|
|
1412
|
+
## A webhook bridge exits at startup, or never binds its port
|
|
1413
|
+
|
|
1414
|
+
### Symptoms
|
|
1415
|
+
|
|
1416
|
+
One of the webhook bridges — `line`, `line-works`, `google-chat`, `messenger`,
|
|
1417
|
+
`teams`, `twilio-sms`, `viber`, `webhook`, `whatsapp` — exits immediately after
|
|
1418
|
+
being started, printing one of:
|
|
1419
|
+
|
|
1420
|
+
```text
|
|
1421
|
+
Port 3002 is already in use. Set LINE_BRIDGE_PORT to a free port, or LINE_BRIDGE_PORT=0 to let the OS pick one.
|
|
1422
|
+
LINE_BRIDGE_PORT="302a" is not a usable port. Set it to an integer from 0 to 65535 (LINE_BRIDGE_PORT=0 asks the OS for a free port), or unset it to use 3002.
|
|
1423
|
+
```
|
|
1424
|
+
|
|
1425
|
+
Both name the env var to change, and each bridge has its own — `WEBHOOK_PORT`,
|
|
1426
|
+
`TWILIO_WEBHOOK_PORT`, `VIBER_WEBHOOK_PORT` and so on. Read the message rather
|
|
1427
|
+
than guessing the name.
|
|
1428
|
+
|
|
1429
|
+
### "Already in use" is usually the server, not a second bridge
|
|
1430
|
+
|
|
1431
|
+
The server's port walk (3002-3021) covers the whole bridge band (3002-3013), so
|
|
1432
|
+
a server that found 3001 busy and moved forward can be sitting on a bridge's
|
|
1433
|
+
default. Check what the server actually bound before moving the bridge:
|
|
1434
|
+
|
|
1435
|
+
```bash
|
|
1436
|
+
cat "${MULMOCLAUDE_WORKSPACE_PATH:-$HOME/mulmoclaude}/.server-port"
|
|
1437
|
+
lsof -nP -iTCP:3002 -sTCP:LISTEN
|
|
1438
|
+
```
|
|
1439
|
+
|
|
1440
|
+
Two ways out, both fine:
|
|
1441
|
+
|
|
1442
|
+
- Give the bridge a port outside the server's band: `LINE_BRIDGE_PORT=3200`.
|
|
1443
|
+
- Let the OS choose: `LINE_BRIDGE_PORT=0`. The startup banner then names the
|
|
1444
|
+
port it actually got — read the banner, not the env var, when tunnelling to it
|
|
1445
|
+
(`Webhook listening on http://localhost:52431/webhook`).
|
|
1446
|
+
|
|
1447
|
+
### Before #3084 both of these were silent
|
|
1448
|
+
|
|
1449
|
+
A bridge of that vintage reads its port as `Number(process.env.X) || <default>`
|
|
1450
|
+
and calls a bare `app.listen`. So a **typo ran on the default without a word**
|
|
1451
|
+
(`302a` → `NaN` → falsy → the default), `X=0` was impossible (falsy too), and a
|
|
1452
|
+
busy port surfaced as an unhandled `EADDRINUSE` with no mention of which env var
|
|
1453
|
+
to change. If neither message above appears and the bridge simply dies, or it is
|
|
1454
|
+
answering on a port you did not ask for, that is the old build: reinstall it
|
|
1455
|
+
(`npm i -g @mulmobridge/<platform>@latest`).
|
|
1456
|
+
|
|
1457
|
+
A bridge that starts but never replies is a different failure — see "A messaging
|
|
1458
|
+
bridge's bot does not reply, and nothing errors" above.
|
|
1459
|
+
|
|
1394
1460
|
## `renderShapeScript` says Chromium is not installed
|
|
1395
1461
|
|
|
1396
1462
|
`renderShapeScript` rasterises a ShapeScript model by driving Puppeteer's
|
|
@@ -1420,3 +1486,52 @@ The same message with `(launch failed: …)` appended means the browser is
|
|
|
1420
1486
|
installed but would not start — usually a sandbox with no permission to
|
|
1421
1487
|
spawn it. Report the parenthesised reason to the user rather than the
|
|
1422
1488
|
install hint alone.
|
|
1489
|
+
|
|
1490
|
+
## The server refuses to start — "MulmoClaude is already running against this workspace"
|
|
1491
|
+
|
|
1492
|
+
### Symptoms
|
|
1493
|
+
|
|
1494
|
+
- `yarn dev`, `yarn server` or `npx mulmoclaude` exits immediately with:
|
|
1495
|
+
`MulmoClaude is already running against this workspace at http://localhost:<port>`
|
|
1496
|
+
- It happens even with a free port named explicitly (`PORT=3100 yarn dev`).
|
|
1497
|
+
|
|
1498
|
+
### Why
|
|
1499
|
+
|
|
1500
|
+
Two servers over one workspace overwrite each other's `.session-token`. After
|
|
1501
|
+
that a stateless plugin dispatch authenticates cleanly against the *wrong*
|
|
1502
|
+
server, while the session-scoped `/api/internal/tool-result` push lands where
|
|
1503
|
+
the session does not exist and is dropped — so plugin views simply never render
|
|
1504
|
+
on one of the two and nothing reports an error. The guard refuses that setup
|
|
1505
|
+
rather than letting it happen quietly (#3079).
|
|
1506
|
+
|
|
1507
|
+
The check reads `<workspace>/.server-port` and probes the port it names, so it
|
|
1508
|
+
is about the WORKSPACE, not the port: a busy 3001 held by some other program
|
|
1509
|
+
still walks forward as before.
|
|
1510
|
+
|
|
1511
|
+
### Fix
|
|
1512
|
+
|
|
1513
|
+
Usually the message is right and there is already a server to use — open the URL
|
|
1514
|
+
it printed.
|
|
1515
|
+
|
|
1516
|
+
To run a genuinely separate second instance, give it its own workspace (no flag
|
|
1517
|
+
needed, this is the supported shape):
|
|
1518
|
+
|
|
1519
|
+
```bash
|
|
1520
|
+
MULMOCLAUDE_WORKSPACE_PATH=~/mulmoclaude-scratch PORT=3100 yarn dev
|
|
1521
|
+
```
|
|
1522
|
+
|
|
1523
|
+
If the first server was killed hard (`kill -9`, a crashed container) the sidecar
|
|
1524
|
+
can name a port something else has since taken; the probe treats a non-MulmoClaude
|
|
1525
|
+
answer as "nobody there", so that case does not stop a launch. A stop therefore
|
|
1526
|
+
means a real instance answered.
|
|
1527
|
+
|
|
1528
|
+
To share one workspace between two servers anyway — accepting the token stomping:
|
|
1529
|
+
|
|
1530
|
+
```bash
|
|
1531
|
+
MULMOCLAUDE_ALLOW_MULTIPLE_INSTANCES=1 yarn dev
|
|
1532
|
+
```
|
|
1533
|
+
|
|
1534
|
+
Use the env var for `yarn dev`. The `--allow-multiple-instances` flag works on
|
|
1535
|
+
`npx mulmoclaude` and `yarn server`, but **not** on `yarn dev`: that is a compound
|
|
1536
|
+
`a && b && c` script, yarn appends extra args to the last command only, and the
|
|
1537
|
+
guard that stops the launch runs in the first one.
|
package/assets/helps/sandbox.md
CHANGED
|
@@ -23,11 +23,11 @@ The container runs with `--cap-drop ALL` and as the host user's UID/GID, so it h
|
|
|
23
23
|
|
|
24
24
|
## Disabling the Sandbox
|
|
25
25
|
|
|
26
|
-
Set the environment variable `DISABLE_SANDBOX=1` to always run the agent directly on the host, even when Docker is available. Equivalently, pass the `--disable-sandbox` CLI flag — `
|
|
26
|
+
Set the environment variable `DISABLE_SANDBOX=1` to always run the agent directly on the host, even when Docker is available. Equivalently, pass the `--disable-sandbox` CLI flag — `npx mulmoclaude --disable-sandbox` or `yarn server --disable-sandbox` (**not** `yarn dev`, whose compound script drops trailing args; use the env var there). The flag form is handy on Windows PowerShell (no inline `VAR=value` syntax), in IDE / launcher run configs, and for quick ad-hoc debugging. Both set the same internal switch; the env var stays supported in parallel.
|
|
27
27
|
|
|
28
28
|
## Debug aids (opt-in env vars)
|
|
29
29
|
|
|
30
|
-
These flags exist for development / debugging only. Off by default so production runs aren't surprised. Each has an equivalent `--flag` CLI form (drop the `=1`, kebab-case the name) accepted by
|
|
30
|
+
These flags exist for development / debugging only. Off by default so production runs aren't surprised. Each has an equivalent `--flag` CLI form (drop the `=1`, kebab-case the name) accepted by `npx mulmoclaude` and `yarn server` — but **not** `yarn dev`, which drops trailing args — e.g. `DISABLE_SANDBOX=1` ≡ `--disable-sandbox`, `PERSIST_TOOL_CALLS=1` ≡ `--persist-tool-calls`, `DISABLE_MACOS_REMINDER_NOTIFICATIONS=1` ≡ `--disable-macos-reminders`, `JOURNAL_FORCE_RUN_ON_STARTUP=1` ≡ `--journal-force-run`, `CHAT_INDEX_FORCE_RUN_ON_STARTUP=1` ≡ `--chat-index-force-run`. Secret-bearing vars (auth token, API keys) have no flag form on purpose — argv is visible via `ps` / shell history.
|
|
31
31
|
|
|
32
32
|
- `DISABLE_SANDBOX=1` — see above. Bypasses the Docker sandbox.
|
|
33
33
|
- `PERSIST_TOOL_CALLS=1` — also persist `tool_call` events to the session jsonl alongside `tool_result`. Useful for reading the args sent to a tool after the run is over (page refresh / server restart). Off by default because args can be large and may carry payload bytes (inline images, full MulmoScript JSON) you didn't expect to land in the jsonl. See [issue #1096](https://github.com/receptron/mulmoclaude/issues/1096) for the rationale.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dist = require("../dist-
|
|
2
|
+
const require_dist = require("../dist-Gj7ygaW2.cjs");
|
|
3
3
|
const require_itemId = require("../itemId-CGT2J7YK.cjs");
|
|
4
|
-
const require_promptSafety = require("../promptSafety-
|
|
4
|
+
const require_promptSafety = require("../promptSafety-caJWd1ZQ.cjs");
|
|
5
5
|
const require_project = require("../project-C1ep9pvo.cjs");
|
|
6
6
|
const require_iconGlyph = require("../iconGlyph-fSBp6k4J.cjs");
|
|
7
|
+
require("../errorMessage-CT-va_Pv.cjs");
|
|
7
8
|
//#region src/collection/core/presentCollection.ts
|
|
8
9
|
var TOOL_NAME = "presentCollection";
|
|
9
10
|
/** Stamp a host's opaque project scope onto a card payload. The ONLY way a
|