@mulmoclaude/core 2.0.0 → 2.0.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/error-recovery.md +32 -0
- package/dist/{atomic-C_7YpMiM.cjs → atomic-DhUk8uiM.cjs} +2 -2
- package/dist/{atomic-C_7YpMiM.cjs.map → atomic-DhUk8uiM.cjs.map} +1 -1
- package/dist/collection/registry/server/index.cjs +21 -26
- package/dist/collection/registry/server/index.cjs.map +1 -1
- package/dist/collection/registry/server/index.js +18 -23
- package/dist/collection/registry/server/index.js.map +1 -1
- package/dist/collection/server/index.cjs +2 -2
- package/dist/collection/server/index.js +2 -2
- package/dist/collection-watchers/index.cjs +3 -3
- package/dist/collection-watchers/index.cjs.map +1 -1
- package/dist/collection-watchers/index.js +3 -3
- package/dist/{discovery-DSLgRQhN.cjs → discovery-B_sHig7n.cjs} +5 -5
- package/dist/{discovery-DSLgRQhN.cjs.map → discovery-B_sHig7n.cjs.map} +1 -1
- package/dist/{discovery-BSedPW8A.js → discovery-BvnXyUel.js} +3 -3
- package/dist/{discovery-BSedPW8A.js.map → discovery-BvnXyUel.js.map} +1 -1
- package/dist/dist-CsgSfWwR.cjs.map +1 -1
- package/dist/dist-D8zokgGo.js.map +1 -1
- package/dist/feeds/paths.cjs +1 -1
- package/dist/feeds/server/index.cjs +5 -5
- package/dist/feeds/server/index.cjs.map +1 -1
- package/dist/feeds/server/index.js +4 -4
- package/dist/feeds/server/index.js.map +1 -1
- package/dist/file-change/index.cjs +1 -1
- package/dist/file-change/index.cjs.map +1 -1
- package/dist/files/index.cjs +3 -3
- package/dist/files/index.cjs.map +1 -1
- package/dist/google/index.cjs +7 -6
- package/dist/google/index.cjs.map +1 -1
- package/dist/google/index.js +5 -4
- package/dist/google/index.js.map +1 -1
- package/dist/notifier/index.cjs +1 -1
- package/dist/notifier/index.js +1 -1
- package/dist/{notifier-CKFVVwDP.cjs → notifier-DZJj0sOh.cjs} +2 -2
- package/dist/{notifier-CKFVVwDP.cjs.map → notifier-DZJj0sOh.cjs.map} +1 -1
- package/dist/{notifier-CQD8NljP.js → notifier-DhnwR82U.js} +2 -2
- package/dist/{notifier-CQD8NljP.js.map → notifier-DhnwR82U.js.map} +1 -1
- package/dist/plugin-vue/i18n.cjs.map +1 -1
- package/dist/plugin-vue/index.cjs +39 -10
- package/dist/plugin-vue/index.cjs.map +1 -1
- package/dist/plugin-vue/index.js +39 -10
- package/dist/plugin-vue/index.js.map +1 -1
- package/dist/{relPath-CgGi4-Nv.cjs → relPath-CTAjGdCL.cjs} +2 -2
- package/dist/{relPath-CgGi4-Nv.cjs.map → relPath-CTAjGdCL.cjs.map} +1 -1
- package/dist/remote-host/server/index.cjs +3 -2
- package/dist/remote-host/server/index.cjs.map +1 -1
- package/dist/remote-host/server/index.js +3 -2
- package/dist/remote-host/server/index.js.map +1 -1
- package/dist/remote-host-CtQjagPt.cjs.map +1 -1
- package/dist/{rolldown-runtime-D6vf50IK.cjs → rolldown-runtime-VH7oDXx4.cjs} +1 -1
- package/dist/scheduler/index.cjs +6 -4
- package/dist/scheduler/index.cjs.map +1 -1
- package/dist/scheduler/index.js +5 -3
- package/dist/scheduler/index.js.map +1 -1
- package/dist/{server-B78f_bnY.js → server-DJt6USBQ.js} +11 -7
- package/dist/{server-B78f_bnY.js.map → server-DJt6USBQ.js.map} +1 -1
- package/dist/{server-By4oSql2.cjs → server-DoyGZMPS.cjs} +14 -10
- package/dist/{server-By4oSql2.cjs.map → server-DoyGZMPS.cjs.map} +1 -1
- package/dist/skill-bridge/index.cjs +1 -1
- package/dist/skill-bridge/index.cjs.map +1 -1
- package/dist/utils/fetch.cjs +1 -1
- package/dist/utils/fetch.cjs.map +1 -1
- package/dist/utils/fetch.js +1 -1
- package/dist/utils/fetch.js.map +1 -1
- package/dist/whisper/client.cjs.map +1 -1
- package/dist/whisper/client.js.map +1 -1
- package/dist/whisper/index.cjs +1 -1
- package/dist/whisper/index.cjs.map +1 -1
- package/dist/wiki/index.cjs +2 -1
- package/dist/wiki/index.cjs.map +1 -1
- package/dist/wiki/index.js +2 -1
- package/dist/wiki/index.js.map +1 -1
- package/dist/wiki/paths.cjs +1 -1
- package/dist/wiki/server/index.cjs +5 -3
- package/dist/wiki/server/index.cjs.map +1 -1
- package/dist/wiki/server/index.js +4 -2
- package/dist/wiki/server/index.js.map +1 -1
- package/dist/workspace-setup/index.js.map +1 -1
- package/package.json +6 -6
|
@@ -863,3 +863,35 @@ afterwards; the load happens once at boot.
|
|
|
863
863
|
Do NOT tell the user to re-check the spelling in `.env`, add the key
|
|
864
864
|
again, or move it elsewhere; the file is already correct, and it is being
|
|
865
865
|
read. The conflict is the whole problem.
|
|
866
|
+
|
|
867
|
+
## A tool your own instructions describe returns "No such tool available"
|
|
868
|
+
|
|
869
|
+
### Symptoms
|
|
870
|
+
|
|
871
|
+
- The Plugin Instructions section of your system prompt documents a tool
|
|
872
|
+
(`mcp__mulmoclaude__google`, `mcp__mulmoclaude__manageSpotify`, any
|
|
873
|
+
plugin-backed name), but calling it errors with `No such tool available`.
|
|
874
|
+
- `ToolSearch select:<that name>` reports no matching deferred tool either.
|
|
875
|
+
- Static tools in the same session (`presentDocument`, `presentForm`, …) work.
|
|
876
|
+
|
|
877
|
+
### Cause
|
|
878
|
+
|
|
879
|
+
The tool surface is published by a separate MCP broker process, and plugin-backed
|
|
880
|
+
tools register there a moment after the session's tool list is first taken. A
|
|
881
|
+
session that captured the list too early keeps one that lacks exactly those
|
|
882
|
+
tools — while the system prompt, built in the server where the plugin IS
|
|
883
|
+
registered, still describes them.
|
|
884
|
+
|
|
885
|
+
### Fix
|
|
886
|
+
|
|
887
|
+
Tell the user plainly that the tool is unavailable in THIS session and that
|
|
888
|
+
starting a new chat re-takes the tool list. Do NOT invent a fallback: reading
|
|
889
|
+
the account's stored credentials, shelling out to a provider CLI, or
|
|
890
|
+
reconstructing the call by hand is worse than the missing tool, and it is not
|
|
891
|
+
what the user asked for.
|
|
892
|
+
|
|
893
|
+
If a new chat has the same gap, the broker did not publish the tool at all.
|
|
894
|
+
Ask the user for the server log around the session start — the broker prints
|
|
895
|
+
`[mcp-server] publishing N tools: …` and, when a promised tool is missing,
|
|
896
|
+
`[mcp-server] advertised but NOT published (check plugin load above): …`. That
|
|
897
|
+
second line, with the plugin-load errors above it, is what a bug report needs.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_rolldown_runtime = require("./rolldown-runtime-
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
|
|
2
2
|
let node_fs = require("node:fs");
|
|
3
3
|
let node_path = require("node:path");
|
|
4
4
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
@@ -99,4 +99,4 @@ Object.defineProperty(exports, "writeFileAtomicSync", {
|
|
|
99
99
|
}
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
//# sourceMappingURL=atomic-
|
|
102
|
+
//# sourceMappingURL=atomic-DhUk8uiM.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomic-
|
|
1
|
+
{"version":3,"file":"atomic-DhUk8uiM.cjs","names":[],"sources":["../src/files/atomic.ts"],"sourcesContent":["// rename(2) is atomic on POSIX; Node's Windows fallback (copy+unlink) is still safer than truncating in place.\n// Readers always see either the old file or the new — never a half-written one.\n//\n// Single source of truth for atomic file writes across the whole monorepo\n// (host, core, plugins). Previously copy-pasted four times, so a Windows retry\n// fix landed in only one (#2399, precedent #2222).\n\nimport { mkdirSync, promises, renameSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { randomBytes } from \"node:crypto\";\n\nexport interface WriteAtomicOptions {\n mode?: number;\n /** Give the staging file a random suffix so concurrent writers to the same\n * destination can't collide at the OS layer.\n *\n * Defaults to `true`, and opting out is almost always wrong. A shared\n * `${filePath}.tmp` means two writers of one file race: the second write\n * overwrites the first's staging file, or one rename/unlink pulls it out\n * from under the other, surfacing as `ENOENT … rename '<file>.tmp'`. That is\n * not theoretical — it fired in production on session meta, where ten\n * distinct callers (`setClaudeSessionId`, `backfillOrigin`,\n * `incrementUserQueryCount`, …) all write the same `<sessionId>.json`\n * (#2222).\n *\n * Pass `false` only when you specifically need the staging path to be\n * predictable (e.g. a single-writer token file, or a test that pre-creates\n * it to force a write failure). */\n uniqueTmp?: boolean;\n}\n\n// Unique staging names are the safe default: the cost is a random suffix, the\n// cost of the alternative is a lost update under concurrency (#2222).\nconst DEFAULT_UNIQUE_TMP = true;\n\nfunction tmpPathFor(filePath: string, uniqueTmp: boolean | undefined): string {\n return (uniqueTmp ?? DEFAULT_UNIQUE_TMP) ? `${filePath}.${randomBytes(6).toString(\"hex\")}.tmp` : `${filePath}.tmp`;\n}\n\n// On Windows, AV / Search Indexer / Defender briefly hold handles and rename trips EPERM/EBUSY/EACCES. Retry loop is\n// gated to Windows because POSIX EPERM means a real perm problem (read-only fs, sticky, cross-device) — retrying\n// just adds latency before the inevitable throw.\nconst IS_WINDOWS = process.platform === \"win32\";\nconst RENAME_RETRY_DELAYS_MS = [30, 100, 300] as const;\n\nfunction hasErrnoCode(err: unknown): err is { code: string } {\n return typeof err === \"object\" && err !== null && \"code\" in err && typeof err.code === \"string\";\n}\n\n// `isWindows` is a parameter (defaulting to the real platform) so the safety-critical decision is testable on any OS.\nexport function isTransientRenameError(err: unknown, isWindows: boolean = IS_WINDOWS): boolean {\n if (!isWindows || !hasErrnoCode(err)) return false;\n return err.code === \"EPERM\" || err.code === \"EBUSY\" || err.code === \"EACCES\";\n}\n\n// Injectable so a test can drive the retry path (fail-then-succeed rename, no-op sleep, isWindows=true) on any OS.\nexport interface RenameRetryDeps {\n rename: (fromPath: string, toPath: string) => Promise<void>;\n sleep: (millis: number) => Promise<void>;\n isWindows: boolean;\n}\n\nconst defaultRenameRetryDeps: RenameRetryDeps = {\n rename: (fromPath, toPath) => promises.rename(fromPath, toPath),\n sleep: (millis) => new Promise((resolve) => setTimeout(resolve, millis)),\n isWindows: IS_WINDOWS,\n};\n\nexport async function renameWithWindowsRetry(fromPath: string, toPath: string, deps: RenameRetryDeps = defaultRenameRetryDeps): Promise<void> {\n for (const delayMs of RENAME_RETRY_DELAYS_MS) {\n try {\n await deps.rename(fromPath, toPath);\n return;\n } catch (err) {\n if (!isTransientRenameError(err, deps.isWindows)) throw err;\n await deps.sleep(delayMs);\n }\n }\n // Final attempt — let any error propagate.\n await deps.rename(fromPath, toPath);\n}\n\n// Atomics.wait parks the thread instead of busy-spinning. Only on the Windows-rename retry path, total ≤ ~430ms.\nconst SYNC_SLEEP_BUF = new Int32Array(new SharedArrayBuffer(4));\nfunction sleepSync(millis: number): void {\n Atomics.wait(SYNC_SLEEP_BUF, 0, 0, millis);\n}\n\n// Deliberate async/sync twin of RenameRetryDeps: `sleep` blocks the thread instead of returning a Promise.\nexport interface RenameRetryDepsSync {\n rename: (fromPath: string, toPath: string) => void;\n sleep: (millis: number) => void;\n isWindows: boolean;\n}\n\nconst defaultRenameRetryDepsSync: RenameRetryDepsSync = {\n rename: (fromPath, toPath) => renameSync(fromPath, toPath),\n sleep: sleepSync,\n isWindows: IS_WINDOWS,\n};\n\nexport function renameSyncWithWindowsRetry(fromPath: string, toPath: string, deps: RenameRetryDepsSync = defaultRenameRetryDepsSync): void {\n for (const delayMs of RENAME_RETRY_DELAYS_MS) {\n try {\n deps.rename(fromPath, toPath);\n return;\n } catch (err) {\n if (!isTransientRenameError(err, deps.isWindows)) throw err;\n deps.sleep(delayMs);\n }\n }\n deps.rename(fromPath, toPath);\n}\n\n// Forcing utf-8 on a Uint8Array would re-encode the bytes — wrong for PNGs and other binary blobs.\nfunction writeOptionsFor(content: string | Uint8Array, mode: number | undefined): { encoding?: \"utf-8\" | undefined; mode?: number | undefined } {\n return typeof content === \"string\" ? { encoding: \"utf-8\", mode } : { mode };\n}\n\nexport async function writeFileAtomic(filePath: string, content: string | Uint8Array, opts: WriteAtomicOptions = {}): Promise<void> {\n const tmp = tmpPathFor(filePath, opts.uniqueTmp);\n await promises.mkdir(path.dirname(filePath), { recursive: true });\n try {\n await promises.writeFile(tmp, content, writeOptionsFor(content, opts.mode));\n await renameWithWindowsRetry(tmp, filePath);\n } catch (err) {\n await promises.unlink(tmp).catch(() => {});\n throw err;\n }\n}\n\nexport function writeFileAtomicSync(filePath: string, content: string | Uint8Array, opts: WriteAtomicOptions = {}): void {\n const tmp = tmpPathFor(filePath, opts.uniqueTmp);\n mkdirSync(path.dirname(filePath), { recursive: true });\n try {\n writeFileSync(tmp, content, writeOptionsFor(content, opts.mode));\n renameSyncWithWindowsRetry(tmp, filePath);\n } catch (err) {\n try {\n unlinkSync(tmp);\n } catch {\n // best-effort cleanup\n }\n throw err;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_rolldown_runtime = require("../../../rolldown-runtime-
|
|
2
|
+
const require_rolldown_runtime = require("../../../rolldown-runtime-VH7oDXx4.cjs");
|
|
3
3
|
const require_dist = require("../../../dist-CsgSfWwR.cjs");
|
|
4
|
-
const require_atomic = require("../../../atomic-
|
|
5
|
-
const require_relPath = require("../../../relPath-
|
|
4
|
+
const require_atomic = require("../../../atomic-DhUk8uiM.cjs");
|
|
5
|
+
const require_relPath = require("../../../relPath-CTAjGdCL.cjs");
|
|
6
6
|
const require_utils_fetch = require("../../../utils/fetch.cjs");
|
|
7
|
-
const require_discovery = require("../../../discovery-
|
|
7
|
+
const require_discovery = require("../../../discovery-B_sHig7n.cjs");
|
|
8
8
|
const require_templatePath = require("../../../templatePath-27vUZowm.cjs");
|
|
9
|
-
const require_server = require("../../../server-
|
|
9
|
+
const require_server = require("../../../server-DoyGZMPS.cjs");
|
|
10
10
|
const require_skill_bridge_index = require("../../../skill-bridge/index.cjs");
|
|
11
11
|
const require_types = require("../../../types-CNqkLT4M.cjs");
|
|
12
12
|
let node_fs = require("node:fs");
|
|
@@ -145,7 +145,8 @@ async function loadFromNetwork(descriptor) {
|
|
|
145
145
|
status: STATUS_BAD_GATEWAY$2,
|
|
146
146
|
error: `registry responded ${res.status}`
|
|
147
147
|
};
|
|
148
|
-
const
|
|
148
|
+
const json = await res.json().catch(() => null);
|
|
149
|
+
const parsed = require_types.parseRegistryIndex(json, descriptor.name);
|
|
149
150
|
if (!parsed.ok) {
|
|
150
151
|
require_discovery.log.warn("collections-registry", "index invalid", {
|
|
151
152
|
registry: descriptor.name,
|
|
@@ -626,7 +627,8 @@ function bridgeAllowlistFiles(bundle) {
|
|
|
626
627
|
* mirror files left over from a previous install so we can prune them after
|
|
627
628
|
* writing the new ones. */
|
|
628
629
|
async function listFilesRecursive(root, prefix = "") {
|
|
629
|
-
const
|
|
630
|
+
const dir = prefix ? node_path.default.join(root, ...prefix.split("/")) : root;
|
|
631
|
+
const entries = await (0, node_fs_promises.readdir)(dir, { withFileTypes: true }).catch(() => []);
|
|
630
632
|
const out = [];
|
|
631
633
|
for (const entry of entries) {
|
|
632
634
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
@@ -935,35 +937,28 @@ var DOUBLE_QUOTE_ESCAPES = {
|
|
|
935
937
|
t: " "
|
|
936
938
|
};
|
|
937
939
|
var unescapeDoubleQuote = (next) => DOUBLE_QUOTE_ESCAPES[next] ?? next;
|
|
938
|
-
function
|
|
940
|
+
function scanQuotedScalar(value, quote, readEscape) {
|
|
939
941
|
const out = [];
|
|
940
942
|
for (let i = 1; i < value.length; i += 1) {
|
|
941
|
-
const
|
|
942
|
-
if (
|
|
943
|
-
out.push(
|
|
943
|
+
const escaped = readEscape(value, i);
|
|
944
|
+
if (escaped !== null) {
|
|
945
|
+
out.push(escaped);
|
|
944
946
|
i += 1;
|
|
945
947
|
continue;
|
|
946
948
|
}
|
|
947
|
-
|
|
949
|
+
const char = value.charAt(i);
|
|
950
|
+
if (char === quote) return isOnlyTrailingComment(value.slice(i + 1)) ? out.join("") : null;
|
|
948
951
|
out.push(char);
|
|
949
952
|
}
|
|
950
953
|
return null;
|
|
951
954
|
}
|
|
955
|
+
var readDoubleQuoteEscape = (value, index) => value.charAt(index) === "\\" && index + 1 < value.length ? unescapeDoubleQuote(value.charAt(index + 1)) : null;
|
|
956
|
+
var readSingleQuoteEscape = (value, index) => value.charAt(index) === "'" && value[index + 1] === "'" ? "'" : null;
|
|
957
|
+
function parseDoubleQuoted(value) {
|
|
958
|
+
return scanQuotedScalar(value, "\"", readDoubleQuoteEscape);
|
|
959
|
+
}
|
|
952
960
|
function parseSingleQuoted(value) {
|
|
953
|
-
|
|
954
|
-
for (let i = 1; i < value.length; i += 1) {
|
|
955
|
-
const char = value.charAt(i);
|
|
956
|
-
if (char === "'") {
|
|
957
|
-
if (value[i + 1] === "'") {
|
|
958
|
-
out.push("'");
|
|
959
|
-
i += 1;
|
|
960
|
-
continue;
|
|
961
|
-
}
|
|
962
|
-
return isOnlyTrailingComment(value.slice(i + 1)) ? out.join("") : null;
|
|
963
|
-
}
|
|
964
|
-
out.push(char);
|
|
965
|
-
}
|
|
966
|
-
return null;
|
|
961
|
+
return scanQuotedScalar(value, "'", readSingleQuoteEscape);
|
|
967
962
|
}
|
|
968
963
|
function stripPlainComment(value) {
|
|
969
964
|
for (let i = 0; i < value.length; i += 1) if (value[i] === "#" && (i === 0 || isYamlSpace(value[i - 1]))) return value.slice(0, i);
|