@mulmoclaude/core 1.2.0 → 1.3.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/collection/core/chatSeed.d.ts +4 -0
- package/dist/collection/core/completion.d.ts +32 -0
- package/dist/collection/core/ids.d.ts +5 -0
- package/dist/collection/core/recordKeys.d.ts +7 -0
- package/dist/collection/index.cjs +25 -2
- package/dist/collection/index.cjs.map +1 -1
- package/dist/collection/index.d.ts +1 -0
- package/dist/collection/index.js +20 -3
- package/dist/collection/index.js.map +1 -1
- package/dist/collection/registry/server/index.cjs +4 -3
- package/dist/collection/registry/server/index.cjs.map +1 -1
- package/dist/collection/registry/server/index.js +4 -3
- package/dist/collection/registry/server/index.js.map +1 -1
- package/dist/collection/server/index.cjs +3 -3
- package/dist/collection/server/index.js +3 -3
- package/dist/collection-watchers/index.cjs +4 -4
- package/dist/collection-watchers/index.js +4 -4
- package/dist/{discovery-UxkvBxV-.cjs → discovery--kRUWed0.cjs} +2 -2
- package/dist/{discovery-UxkvBxV-.cjs.map → discovery--kRUWed0.cjs.map} +1 -1
- package/dist/{discovery-DYlEOa9a.js → discovery-CKR4TOX3.js} +2 -2
- package/dist/{discovery-DYlEOa9a.js.map → discovery-CKR4TOX3.js.map} +1 -1
- package/dist/feeds/index.cjs +2 -2
- package/dist/feeds/index.js +2 -2
- package/dist/feeds/server/index.cjs +4 -4
- package/dist/feeds/server/index.js +4 -4
- package/dist/files/index.cjs +3 -0
- package/dist/files/index.cjs.map +1 -1
- package/dist/files/index.d.ts +1 -0
- package/dist/files/index.js +2 -1
- package/dist/files/index.js.map +1 -1
- package/dist/files/relPath.d.ts +23 -0
- package/dist/google/collectionSync.d.ts +30 -0
- package/dist/google/index.cjs +78 -6
- package/dist/google/index.cjs.map +1 -1
- package/dist/google/index.d.ts +1 -1
- package/dist/google/index.js +76 -7
- package/dist/google/index.js.map +1 -1
- package/dist/{graph-o5FZZbXf.js → graph-BcwqiSpR.js} +2 -14
- package/dist/graph-BcwqiSpR.js.map +1 -0
- package/dist/{graph-2R4HbQAg.cjs → graph-DjE1Az1C.cjs} +2 -14
- package/dist/graph-DjE1Az1C.cjs.map +1 -0
- package/dist/{ids-BJ7rdrDN.cjs → ids-BnTh3Hl0.cjs} +13 -1
- package/dist/{ids-BJ7rdrDN.cjs.map → ids-BnTh3Hl0.cjs.map} +1 -1
- package/dist/{ids-Bv6AOW9Z.js → ids-s4GfmE93.js} +8 -2
- package/dist/{ids-Bv6AOW9Z.js.map → ids-s4GfmE93.js.map} +1 -1
- package/dist/{ingestTypes-DuCiZqye.js → ingestTypes-L59cIGgX.js} +2 -2
- package/dist/{ingestTypes-DuCiZqye.js.map → ingestTypes-L59cIGgX.js.map} +1 -1
- package/dist/{ingestTypes-CkbM-zrO.cjs → ingestTypes-xX8VpQqh.cjs} +2 -2
- package/dist/{ingestTypes-CkbM-zrO.cjs.map → ingestTypes-xX8VpQqh.cjs.map} +1 -1
- package/dist/{promptSafety-BNelBKhh.js → promptSafety-CQ5Un4wi.js} +28 -3
- package/dist/promptSafety-CQ5Un4wi.js.map +1 -0
- package/dist/{promptSafety-QAtADXUF.cjs → promptSafety-DfZYNtjK.cjs} +45 -2
- package/dist/promptSafety-DfZYNtjK.cjs.map +1 -0
- package/dist/relPath-CgGi4-Nv.cjs +46 -0
- package/dist/relPath-CgGi4-Nv.cjs.map +1 -0
- package/dist/relPath-DW8MC8VO.js +33 -0
- package/dist/relPath-DW8MC8VO.js.map +1 -0
- package/dist/remote-host/server/hostRunner.d.ts +3 -0
- package/dist/remote-host/server/index.cjs +69 -16
- package/dist/remote-host/server/index.cjs.map +1 -1
- package/dist/remote-host/server/index.js +69 -16
- package/dist/remote-host/server/index.js.map +1 -1
- package/dist/{server-CnwgECW-.js → server-D_6FLygK.js} +9 -5
- package/dist/server-D_6FLygK.js.map +1 -0
- package/dist/{server-DFo3zFYB.cjs → server-gEOeV_Nv.cjs} +9 -5
- package/dist/server-gEOeV_Nv.cjs.map +1 -0
- package/dist/wiki/index.cjs +20 -12
- package/dist/wiki/index.cjs.map +1 -1
- package/dist/wiki/index.js +20 -12
- package/dist/wiki/index.js.map +1 -1
- package/dist/wiki/link.d.ts +7 -1
- package/dist/wiki/render.d.ts +3 -3
- package/dist/wiki/server/index.cjs +1 -1
- package/dist/wiki/server/index.js +1 -1
- package/package.json +5 -4
- package/dist/graph-2R4HbQAg.cjs.map +0 -1
- package/dist/graph-o5FZZbXf.js.map +0 -1
- package/dist/promptSafety-BNelBKhh.js.map +0 -1
- package/dist/promptSafety-QAtADXUF.cjs.map +0 -1
- package/dist/server-CnwgECW-.js.map +0 -1
- package/dist/server-DFo3zFYB.cjs.map +0 -1
package/dist/feeds/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_ids = require("../ids-
|
|
3
|
-
const require_ingestTypes = require("../ingestTypes-
|
|
2
|
+
const require_ids = require("../ids-BnTh3Hl0.cjs");
|
|
3
|
+
const require_ingestTypes = require("../ingestTypes-xX8VpQqh.cjs");
|
|
4
4
|
exports.AGENT_INGEST_KIND = require_ingestTypes.AGENT_INGEST_KIND;
|
|
5
5
|
exports.DEFAULT_FEED_MAX_ITEMS = require_ingestTypes.DEFAULT_FEED_MAX_ITEMS;
|
|
6
6
|
exports.FEED_SCHEDULES = require_ids.FEED_SCHEDULES;
|
package/dist/feeds/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as DEFAULT_FEED_MAX_ITEMS, r as isFeedSchedule, t as AGENT_INGEST_KIND } from "../ingestTypes-
|
|
1
|
+
import { l as FEED_SCHEDULES, u as INGEST_KINDS } from "../ids-s4GfmE93.js";
|
|
2
|
+
import { n as DEFAULT_FEED_MAX_ITEMS, r as isFeedSchedule, t as AGENT_INGEST_KIND } from "../ingestTypes-L59cIGgX.js";
|
|
3
3
|
export { AGENT_INGEST_KIND, DEFAULT_FEED_MAX_ITEMS, FEED_SCHEDULES, INGEST_KINDS, isFeedSchedule };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("../../rolldown-runtime-D6vf50IK.cjs");
|
|
3
|
-
const require_ids = require("../../ids-
|
|
4
|
-
const require_discovery = require("../../discovery
|
|
5
|
-
const require_server = require("../../server-
|
|
6
|
-
const require_ingestTypes = require("../../ingestTypes-CkbM-zrO.cjs");
|
|
3
|
+
const require_ids = require("../../ids-BnTh3Hl0.cjs");
|
|
4
|
+
const require_discovery = require("../../discovery--kRUWed0.cjs");
|
|
5
|
+
const require_server = require("../../server-gEOeV_Nv.cjs");
|
|
7
6
|
const require_feeds_paths = require("../paths.cjs");
|
|
7
|
+
const require_ingestTypes = require("../../ingestTypes-xX8VpQqh.cjs");
|
|
8
8
|
const require_notifier = require("../../notifier-tMsAXyXp.cjs");
|
|
9
9
|
let node_path = require("node:path");
|
|
10
10
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { N as listItems, V as resolveDataDir, W as safeSlugName, d as storeFor, et as createForwardingLogger, n as discoverCollections, tt as createHostSlot } from "../../discovery-
|
|
3
|
-
import { A as buildCollectionActionSeedPrompt, P as readSkillTemplate, j as promptPathsFor } from "../../server-
|
|
4
|
-
import { n as DEFAULT_FEED_MAX_ITEMS, r as isFeedSchedule, t as AGENT_INGEST_KIND } from "../../ingestTypes-DuCiZqye.js";
|
|
1
|
+
import { l as FEED_SCHEDULES, u as INGEST_KINDS } from "../../ids-s4GfmE93.js";
|
|
2
|
+
import { N as listItems, V as resolveDataDir, W as safeSlugName, d as storeFor, et as createForwardingLogger, n as discoverCollections, tt as createHostSlot } from "../../discovery-CKR4TOX3.js";
|
|
3
|
+
import { A as buildCollectionActionSeedPrompt, P as readSkillTemplate, j as promptPathsFor } from "../../server-D_6FLygK.js";
|
|
5
4
|
import { FEEDS_DIR, feedDir, feedStatePath, feedsRoot, ingestStateDir, ingestStatePath } from "../paths.js";
|
|
5
|
+
import { n as DEFAULT_FEED_MAX_ITEMS, r as isFeedSchedule, t as AGENT_INGEST_KIND } from "../../ingestTypes-L59cIGgX.js";
|
|
6
6
|
import { d as publish, n as clear } from "../../notifier-BdA5qzhe.js";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { createHash } from "node:crypto";
|
package/dist/files/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("../rolldown-runtime-D6vf50IK.cjs");
|
|
3
3
|
const require_atomic = require("../atomic-C_7YpMiM.cjs");
|
|
4
|
+
const require_relPath = require("../relPath-CgGi4-Nv.cjs");
|
|
4
5
|
let node_fs = require("node:fs");
|
|
5
6
|
let node_path = require("node:path");
|
|
6
7
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
@@ -39,7 +40,9 @@ function realpathOrNull(absPath) {
|
|
|
39
40
|
}
|
|
40
41
|
//#endregion
|
|
41
42
|
exports.isEnoent = isEnoent;
|
|
43
|
+
exports.joinPosixRelPath = require_relPath.joinPosixRelPath;
|
|
42
44
|
exports.resolveWithinRoot = resolveWithinRoot;
|
|
45
|
+
exports.toPosixRelPath = require_relPath.toPosixRelPath;
|
|
43
46
|
exports.writeFileAtomic = require_atomic.writeFileAtomic;
|
|
44
47
|
exports.writeFileAtomicSync = require_atomic.writeFileAtomicSync;
|
|
45
48
|
exports.writeJsonAtomic = writeJsonAtomic;
|
package/dist/files/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/files/json.ts","../../src/files/safe.ts"],"sourcesContent":["import { writeFileAtomic, type WriteAtomicOptions } from \"./atomic.js\";\n\nconst JSON_INDENT = 2;\n\n/** Atomic JSON write (2-space indent) — serialize then write through the atomic\n * tmp-file + rename seam so a reader never sees a half-written document. */\nexport async function writeJsonAtomic(filePath: string, data: unknown, opts: WriteAtomicOptions = {}): Promise<void> {\n await writeFileAtomic(filePath, JSON.stringify(data, null, JSON_INDENT), opts);\n}\n","import { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** True for a `not found` filesystem error (ENOENT) — lets callers treat a\n * missing file as an empty/default result instead of a thrown error. */\nexport function isEnoent(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && \"code\" in err && err.code === \"ENOENT\";\n}\n\n/** Realpath-based read-time containment: resolve `relPath` against the root's\n * realpath and require the target's realpath to stay inside it. Returns null\n * on ENOENT or traversal (symlink escapes included). `rootReal` MUST already\n * be a realpath. The one implementation for host and plugins (#2461) — this\n * security-critical primitive must not drift per consumer. */\nexport function resolveWithinRoot(rootReal: string, relPath: string): string | null {\n const normalized = path.normalize(relPath || \"\");\n const resolved = path.resolve(rootReal, normalized);\n const resolvedReal = realpathOrNull(resolved);\n if (resolvedReal === null) return null;\n if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + path.sep)) {\n return null;\n }\n return resolvedReal;\n}\n\nfunction realpathOrNull(absPath: string): string | null {\n try {\n return realpathSync(absPath);\n } catch {\n return null;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/files/json.ts","../../src/files/safe.ts"],"sourcesContent":["import { writeFileAtomic, type WriteAtomicOptions } from \"./atomic.js\";\n\nconst JSON_INDENT = 2;\n\n/** Atomic JSON write (2-space indent) — serialize then write through the atomic\n * tmp-file + rename seam so a reader never sees a half-written document. */\nexport async function writeJsonAtomic(filePath: string, data: unknown, opts: WriteAtomicOptions = {}): Promise<void> {\n await writeFileAtomic(filePath, JSON.stringify(data, null, JSON_INDENT), opts);\n}\n","import { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** True for a `not found` filesystem error (ENOENT) — lets callers treat a\n * missing file as an empty/default result instead of a thrown error. */\nexport function isEnoent(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && \"code\" in err && err.code === \"ENOENT\";\n}\n\n/** Realpath-based read-time containment: resolve `relPath` against the root's\n * realpath and require the target's realpath to stay inside it. Returns null\n * on ENOENT or traversal (symlink escapes included). `rootReal` MUST already\n * be a realpath. The one implementation for host and plugins (#2461) — this\n * security-critical primitive must not drift per consumer. */\nexport function resolveWithinRoot(rootReal: string, relPath: string): string | null {\n const normalized = path.normalize(relPath || \"\");\n const resolved = path.resolve(rootReal, normalized);\n const resolvedReal = realpathOrNull(resolved);\n if (resolvedReal === null) return null;\n if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + path.sep)) {\n return null;\n }\n return resolvedReal;\n}\n\nfunction realpathOrNull(absPath: string): string | null {\n try {\n return realpathSync(absPath);\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;;;;;AAEA,IAAM,cAAc;;;AAIpB,eAAsB,gBAAgB,UAAkB,MAAe,OAA2B,CAAC,GAAkB;CACnH,MAAM,eAAA,gBAAgB,UAAU,KAAK,UAAU,MAAM,MAAM,WAAW,GAAG,IAAI;AAC/E;;;;;ACHA,SAAgB,SAAS,KAAuB;CAC9C,OAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU,OAAO,IAAI,SAAS;AAClF;;;;;;AAOA,SAAgB,kBAAkB,UAAkB,SAAgC;CAClF,MAAM,aAAa,UAAA,QAAK,UAAU,WAAW,EAAE;CAE/C,MAAM,eAAe,eADJ,UAAA,QAAK,QAAQ,UAAU,UACJ,CAAQ;CAC5C,IAAI,iBAAiB,MAAM,OAAO;CAClC,IAAI,iBAAiB,YAAY,CAAC,aAAa,WAAW,WAAW,UAAA,QAAK,GAAG,GAC3E,OAAO;CAET,OAAO;AACT;AAEA,SAAS,eAAe,SAAgC;CACtD,IAAI;EACF,QAAA,GAAA,QAAA,aAAA,CAAoB,OAAO;CAC7B,QAAQ;EACN,OAAO;CACT;AACF"}
|
package/dist/files/index.d.ts
CHANGED
package/dist/files/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { n as writeFileAtomicSync, t as writeFileAtomic } from "../atomic-DPpdrJzO.js";
|
|
2
|
+
import { n as toPosixRelPath, t as joinPosixRelPath } from "../relPath-DW8MC8VO.js";
|
|
2
3
|
import { realpathSync } from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
//#region src/files/json.ts
|
|
@@ -35,6 +36,6 @@ function realpathOrNull(absPath) {
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
//#endregion
|
|
38
|
-
export { isEnoent, resolveWithinRoot, writeFileAtomic, writeFileAtomicSync, writeJsonAtomic };
|
|
39
|
+
export { isEnoent, joinPosixRelPath, resolveWithinRoot, toPosixRelPath, writeFileAtomic, writeFileAtomicSync, writeJsonAtomic };
|
|
39
40
|
|
|
40
41
|
//# sourceMappingURL=index.js.map
|
package/dist/files/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/files/json.ts","../../src/files/safe.ts"],"sourcesContent":["import { writeFileAtomic, type WriteAtomicOptions } from \"./atomic.js\";\n\nconst JSON_INDENT = 2;\n\n/** Atomic JSON write (2-space indent) — serialize then write through the atomic\n * tmp-file + rename seam so a reader never sees a half-written document. */\nexport async function writeJsonAtomic(filePath: string, data: unknown, opts: WriteAtomicOptions = {}): Promise<void> {\n await writeFileAtomic(filePath, JSON.stringify(data, null, JSON_INDENT), opts);\n}\n","import { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** True for a `not found` filesystem error (ENOENT) — lets callers treat a\n * missing file as an empty/default result instead of a thrown error. */\nexport function isEnoent(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && \"code\" in err && err.code === \"ENOENT\";\n}\n\n/** Realpath-based read-time containment: resolve `relPath` against the root's\n * realpath and require the target's realpath to stay inside it. Returns null\n * on ENOENT or traversal (symlink escapes included). `rootReal` MUST already\n * be a realpath. The one implementation for host and plugins (#2461) — this\n * security-critical primitive must not drift per consumer. */\nexport function resolveWithinRoot(rootReal: string, relPath: string): string | null {\n const normalized = path.normalize(relPath || \"\");\n const resolved = path.resolve(rootReal, normalized);\n const resolvedReal = realpathOrNull(resolved);\n if (resolvedReal === null) return null;\n if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + path.sep)) {\n return null;\n }\n return resolvedReal;\n}\n\nfunction realpathOrNull(absPath: string): string | null {\n try {\n return realpathSync(absPath);\n } catch {\n return null;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/files/json.ts","../../src/files/safe.ts"],"sourcesContent":["import { writeFileAtomic, type WriteAtomicOptions } from \"./atomic.js\";\n\nconst JSON_INDENT = 2;\n\n/** Atomic JSON write (2-space indent) — serialize then write through the atomic\n * tmp-file + rename seam so a reader never sees a half-written document. */\nexport async function writeJsonAtomic(filePath: string, data: unknown, opts: WriteAtomicOptions = {}): Promise<void> {\n await writeFileAtomic(filePath, JSON.stringify(data, null, JSON_INDENT), opts);\n}\n","import { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** True for a `not found` filesystem error (ENOENT) — lets callers treat a\n * missing file as an empty/default result instead of a thrown error. */\nexport function isEnoent(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && \"code\" in err && err.code === \"ENOENT\";\n}\n\n/** Realpath-based read-time containment: resolve `relPath` against the root's\n * realpath and require the target's realpath to stay inside it. Returns null\n * on ENOENT or traversal (symlink escapes included). `rootReal` MUST already\n * be a realpath. The one implementation for host and plugins (#2461) — this\n * security-critical primitive must not drift per consumer. */\nexport function resolveWithinRoot(rootReal: string, relPath: string): string | null {\n const normalized = path.normalize(relPath || \"\");\n const resolved = path.resolve(rootReal, normalized);\n const resolvedReal = realpathOrNull(resolved);\n if (resolvedReal === null) return null;\n if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + path.sep)) {\n return null;\n }\n return resolvedReal;\n}\n\nfunction realpathOrNull(absPath: string): string | null {\n try {\n return realpathSync(absPath);\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;;AAEA,IAAM,cAAc;;;AAIpB,eAAsB,gBAAgB,UAAkB,MAAe,OAA2B,CAAC,GAAkB;CACnH,MAAM,gBAAgB,UAAU,KAAK,UAAU,MAAM,MAAM,WAAW,GAAG,IAAI;AAC/E;;;;;ACHA,SAAgB,SAAS,KAAuB;CAC9C,OAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU,OAAO,IAAI,SAAS;AAClF;;;;;;AAOA,SAAgB,kBAAkB,UAAkB,SAAgC;CAClF,MAAM,aAAa,KAAK,UAAU,WAAW,EAAE;CAE/C,MAAM,eAAe,eADJ,KAAK,QAAQ,UAAU,UACJ,CAAQ;CAC5C,IAAI,iBAAiB,MAAM,OAAO;CAClC,IAAI,iBAAiB,YAAY,CAAC,aAAa,WAAW,WAAW,KAAK,GAAG,GAC3E,OAAO;CAET,OAAO;AACT;AAEA,SAAS,eAAe,SAAgC;CACtD,IAAI;EACF,OAAO,aAAa,OAAO;CAC7B,QAAQ;EACN,OAAO;CACT;AACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Convert a host-shaped workspace-relative path to the POSIX form.
|
|
2
|
+
*
|
|
3
|
+
* Splits on the host separator rather than rewriting every `\` — on POSIX a
|
|
4
|
+
* backslash is a legal filename character, so a blanket replace would turn the
|
|
5
|
+
* single directory `we\ird` into the two segments `we/ird` and send the write
|
|
6
|
+
* somewhere else. Splitting on `path.sep` is a no-op on POSIX and correct on
|
|
7
|
+
* Windows.
|
|
8
|
+
*
|
|
9
|
+
* `sep` is a parameter so the Windows rule is assertable from a POSIX runner:
|
|
10
|
+
* bound to the host's own separator, the whole rule is invisible outside
|
|
11
|
+
* Windows CI, which is how the backslash form reached main twice (#2540).
|
|
12
|
+
*
|
|
13
|
+
* Separator shape only — it neither validates nor contains. A traversal or a
|
|
14
|
+
* drive-absolute input survives as one, deliberately, so `resolveWithinRoot`
|
|
15
|
+
* downstream can still see the escape it has to refuse. */
|
|
16
|
+
export declare function toPosixRelPath(hostRelPath: string, sep?: string): string;
|
|
17
|
+
/** Append a single path segment to a POSIX workspace-relative path.
|
|
18
|
+
*
|
|
19
|
+
* Separate from `toPosixRelPath` because the inputs differ: this one joins
|
|
20
|
+
* segments that are ALREADY POSIX-shaped (a parent rel path plus one
|
|
21
|
+
* `Dirent.name`), so it must not touch the characters inside them. Use
|
|
22
|
+
* `toPosixRelPath` first when the parent came out of `node:path`. */
|
|
23
|
+
export declare function joinPosixRelPath(dirRelPosix: string, segment: string): string;
|
|
@@ -48,6 +48,10 @@ export declare function classifyDelete(eventId: string, kind: DeleteItemResult["
|
|
|
48
48
|
* those events forever. Fetch once, apply to all, then advance the token.
|
|
49
49
|
* (Codex + CodeRabbit review on #2184.) */
|
|
50
50
|
export declare function syncCalendarGroup(calendarId: string | undefined, collections: readonly LoadedCollection[], workspaceRoot: string): Promise<CalendarCollectionSyncResult[]>;
|
|
51
|
+
/** Liveness of the collections a sync just wrote to, checked against the skill
|
|
52
|
+
* dir `deleteCollection` removes. `exists` is injected so the rule is testable
|
|
53
|
+
* without a filesystem. An empty group has no survivor by definition. */
|
|
54
|
+
export declare function anySyncedCollectionSurvives(collections: readonly Pick<LoadedCollection, "skillDir">[], exists?: (absPath: string) => Promise<boolean>): Promise<boolean>;
|
|
51
55
|
/** Group the declaring collections by the calendar they read, so each calendar
|
|
52
56
|
* is fetched exactly once.
|
|
53
57
|
*
|
|
@@ -57,6 +61,32 @@ export declare function syncCalendarGroup(calendarId: string | undefined, collec
|
|
|
57
61
|
* from under the other — the very loss this grouping exists to prevent
|
|
58
62
|
* (Codex review #2184). */
|
|
59
63
|
export declare function groupByCalendar(collections: readonly LoadedCollection[]): Map<string, LoadedCollection[]>;
|
|
64
|
+
/** The minimum a value needs for the orphan check: just the calendar it reads.
|
|
65
|
+
* Structural so the rule can be exercised without building a LoadedCollection. */
|
|
66
|
+
export interface CalendarDeclaring {
|
|
67
|
+
googleCalendar?: {
|
|
68
|
+
calendarId?: string;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** The canonical calendar whose sync token nothing needs any more, or null.
|
|
72
|
+
*
|
|
73
|
+
* Sync tokens are keyed by calendar, NOT by collection, so a deleted
|
|
74
|
+
* collection's token outlives it. Recreating a collection on the same calendar
|
|
75
|
+
* then resumes from that token and receives only the delta — the new
|
|
76
|
+
* collection never gets the history (#2428).
|
|
77
|
+
*
|
|
78
|
+
* Returns null while ANY remaining collection still reads that calendar:
|
|
79
|
+
* clearing a live calendar's token costs a full re-walk on the next sync. The
|
|
80
|
+
* comparison is on the CANONICAL id for the same reason `groupByCalendar` is —
|
|
81
|
+
* an omitted `calendarId` and an explicit `"primary"` are one calendar. */
|
|
82
|
+
export declare function orphanedCalendarId(deleted: CalendarDeclaring, remaining: readonly CalendarDeclaring[]): string | null;
|
|
83
|
+
/** Drop the sync token of a just-deleted collection's calendar, unless another
|
|
84
|
+
* collection still reads it. Call AFTER the delete lands — the check reads the
|
|
85
|
+
* collections that survive it.
|
|
86
|
+
*
|
|
87
|
+
* Returns the cleared calendar id, or null when nothing was cleared. Never
|
|
88
|
+
* throws: a failed cleanup must not fail the delete it follows. */
|
|
89
|
+
export declare function releaseOrphanedCalendarToken(deleted: CalendarDeclaring, workspaceRoot: string): Promise<string | null>;
|
|
60
90
|
/** Sync every collection that declares `googleCalendar`. Failures are isolated
|
|
61
91
|
* per calendar — one unreachable calendar (or a revoked grant) must not stop
|
|
62
92
|
* the others. */
|
package/dist/google/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ const require_dist = require("../dist-pWpC-b04.cjs");
|
|
|
4
4
|
const require_text = require("../text-CaAh9ZSO.cjs");
|
|
5
5
|
const require_atomic = require("../atomic-C_7YpMiM.cjs");
|
|
6
6
|
const require_utils_fetch = require("../utils/fetch.cjs");
|
|
7
|
-
const require_discovery = require("../discovery
|
|
7
|
+
const require_discovery = require("../discovery--kRUWed0.cjs");
|
|
8
8
|
let node_fs = require("node:fs");
|
|
9
9
|
let node_path = require("node:path");
|
|
10
10
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
@@ -906,13 +906,47 @@ async function syncCalendarGroup(calendarId, collections, workspaceRoot) {
|
|
|
906
906
|
unwritable
|
|
907
907
|
});
|
|
908
908
|
const failed = results.flatMap((entry) => entry.errors);
|
|
909
|
-
if (
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
909
|
+
if (failed.length > 0) {
|
|
910
|
+
log.warn("google", "holding back calendar sync token after failed writes", {
|
|
911
|
+
calendarId,
|
|
912
|
+
failed: failed.length
|
|
913
|
+
});
|
|
914
|
+
return results;
|
|
915
|
+
}
|
|
916
|
+
if (result.nextSyncToken) await advanceToken(calendarId, result.nextSyncToken, collections, workspaceRoot);
|
|
914
917
|
return results;
|
|
915
918
|
}
|
|
919
|
+
/** Save the window's token unless every collection that consumed it was deleted
|
|
920
|
+
* while the sync was in flight.
|
|
921
|
+
*
|
|
922
|
+
* The sync opens with a `discoverCollections()` snapshot, so a delete landing
|
|
923
|
+
* mid-run has already cleared this calendar's token by the time we get here
|
|
924
|
+
* (`releaseOrphanedCalendarToken`). Saving anyway would resurrect exactly the
|
|
925
|
+
* orphan the delete removed, and the next collection on this calendar would
|
|
926
|
+
* resume from a token describing records it never received (#2428).
|
|
927
|
+
*
|
|
928
|
+
* One survivor is enough: it still needs the incremental position. */
|
|
929
|
+
async function advanceToken(calendarId, nextSyncToken, collections, workspaceRoot) {
|
|
930
|
+
if (!await anySyncedCollectionSurvives(collections)) {
|
|
931
|
+
log.info("google", "not advancing the sync token — every collection on this calendar was deleted mid-sync", { calendarId });
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
await saveCalendarSyncToken(calendarId, nextSyncToken, workspaceRoot);
|
|
935
|
+
}
|
|
936
|
+
async function pathExists(absPath) {
|
|
937
|
+
try {
|
|
938
|
+
await (0, node_fs_promises.stat)(absPath);
|
|
939
|
+
return true;
|
|
940
|
+
} catch {
|
|
941
|
+
return false;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
/** Liveness of the collections a sync just wrote to, checked against the skill
|
|
945
|
+
* dir `deleteCollection` removes. `exists` is injected so the rule is testable
|
|
946
|
+
* without a filesystem. An empty group has no survivor by definition. */
|
|
947
|
+
async function anySyncedCollectionSurvives(collections, exists = pathExists) {
|
|
948
|
+
return (await Promise.all(collections.map((collection) => exists(collection.skillDir)))).some(Boolean);
|
|
949
|
+
}
|
|
916
950
|
async function applyEventsToCollection(collection, events, workspaceRoot) {
|
|
917
951
|
const outcomes = [];
|
|
918
952
|
for (const event of events) outcomes.push(await applyEvent(collection, event, workspaceRoot));
|
|
@@ -945,6 +979,41 @@ function groupByCalendar(collections) {
|
|
|
945
979
|
}
|
|
946
980
|
return groups;
|
|
947
981
|
}
|
|
982
|
+
/** The canonical calendar whose sync token nothing needs any more, or null.
|
|
983
|
+
*
|
|
984
|
+
* Sync tokens are keyed by calendar, NOT by collection, so a deleted
|
|
985
|
+
* collection's token outlives it. Recreating a collection on the same calendar
|
|
986
|
+
* then resumes from that token and receives only the delta — the new
|
|
987
|
+
* collection never gets the history (#2428).
|
|
988
|
+
*
|
|
989
|
+
* Returns null while ANY remaining collection still reads that calendar:
|
|
990
|
+
* clearing a live calendar's token costs a full re-walk on the next sync. The
|
|
991
|
+
* comparison is on the CANONICAL id for the same reason `groupByCalendar` is —
|
|
992
|
+
* an omitted `calendarId` and an explicit `"primary"` are one calendar. */
|
|
993
|
+
function orphanedCalendarId(deleted, remaining) {
|
|
994
|
+
if (!deleted.googleCalendar) return null;
|
|
995
|
+
const key = canonicalCalendarId(deleted.googleCalendar.calendarId);
|
|
996
|
+
return remaining.some((other) => other.googleCalendar && canonicalCalendarId(other.googleCalendar.calendarId) === key) ? null : key;
|
|
997
|
+
}
|
|
998
|
+
/** Drop the sync token of a just-deleted collection's calendar, unless another
|
|
999
|
+
* collection still reads it. Call AFTER the delete lands — the check reads the
|
|
1000
|
+
* collections that survive it.
|
|
1001
|
+
*
|
|
1002
|
+
* Returns the cleared calendar id, or null when nothing was cleared. Never
|
|
1003
|
+
* throws: a failed cleanup must not fail the delete it follows. */
|
|
1004
|
+
async function releaseOrphanedCalendarToken(deleted, workspaceRoot) {
|
|
1005
|
+
try {
|
|
1006
|
+
if (!deleted.googleCalendar) return null;
|
|
1007
|
+
const orphaned = orphanedCalendarId(deleted, (await require_discovery.discoverCollections({ workspaceRoot })).map((collection) => collection.schema));
|
|
1008
|
+
if (orphaned === null) return null;
|
|
1009
|
+
await clearCalendarSyncToken(orphaned, workspaceRoot);
|
|
1010
|
+
log.info("google", "cleared the sync token of a calendar no collection reads any more", { calendarId: orphaned });
|
|
1011
|
+
return orphaned;
|
|
1012
|
+
} catch (error) {
|
|
1013
|
+
log.warn("google", "could not release the deleted collection's calendar sync token", { error: String(error) });
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
948
1017
|
/** Sync every collection that declares `googleCalendar`. Failures are isolated
|
|
949
1018
|
* per calendar — one unreachable calendar (or a revoked grant) must not stop
|
|
950
1019
|
* the others. */
|
|
@@ -1147,6 +1216,7 @@ exports.GOOGLE_SCOPES = GOOGLE_SCOPES;
|
|
|
1147
1216
|
exports.GOOGLE_TASKS_SCOPE = GOOGLE_TASKS_SCOPE;
|
|
1148
1217
|
exports.GoogleApiError = GoogleApiError;
|
|
1149
1218
|
exports.MAX_LIST_RESULTS = MAX_LIST_RESULTS;
|
|
1219
|
+
exports.anySyncedCollectionSurvives = anySyncedCollectionSurvives;
|
|
1150
1220
|
exports.assertSafeMimeType = assertSafeMimeType;
|
|
1151
1221
|
exports.authorizeGoogle = authorizeGoogle;
|
|
1152
1222
|
exports.brokerBaseUrl = brokerBaseUrl;
|
|
@@ -1195,8 +1265,10 @@ exports.loadCalendarSyncToken = loadCalendarSyncToken;
|
|
|
1195
1265
|
exports.loadClientSecret = loadClientSecret;
|
|
1196
1266
|
exports.loadGoogleTokens = loadGoogleTokens;
|
|
1197
1267
|
exports.mergeGoogleTokens = mergeGoogleTokens;
|
|
1268
|
+
exports.orphanedCalendarId = orphanedCalendarId;
|
|
1198
1269
|
exports.pickBoundary = pickBoundary;
|
|
1199
1270
|
exports.readDriveFile = readDriveFile;
|
|
1271
|
+
exports.releaseOrphanedCalendarToken = releaseOrphanedCalendarToken;
|
|
1200
1272
|
exports.saveCalendarSyncToken = saveCalendarSyncToken;
|
|
1201
1273
|
exports.saveGoogleTokens = saveGoogleTokens;
|
|
1202
1274
|
exports.syncCalendarEvents = syncCalendarEvents;
|