@kanadego/dsh-heartbeat 1.5.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.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +192 -0
  3. package/assets/frontwin.ps1 +44 -0
  4. package/assets/idle.ps1 +27 -0
  5. package/assets/notify.ps1 +69 -0
  6. package/assets/presets/heartbeat/agent.cordis.yml +66 -0
  7. package/assets/presets/heartbeat/preset.yml +2 -0
  8. package/assets/screenpulse.ps1 +168 -0
  9. package/assets/vault.ps1 +52 -0
  10. package/client.js +428 -0
  11. package/config/busy-rules.json +63 -0
  12. package/config/interests.json +30 -0
  13. package/config/policy.json +57 -0
  14. package/config/profile-schema.json +68 -0
  15. package/config/watchlist.json +9 -0
  16. package/cordis.patch.yml +14 -0
  17. package/dist/bindings-XPPSKILN.js +19 -0
  18. package/dist/bindings-XPPSKILN.js.map +1 -0
  19. package/dist/chunk-2M35HRL6.js +1207 -0
  20. package/dist/chunk-2M35HRL6.js.map +1 -0
  21. package/dist/chunk-4UE74TUB.js +98 -0
  22. package/dist/chunk-4UE74TUB.js.map +1 -0
  23. package/dist/chunk-AISZRA4C.js +235 -0
  24. package/dist/chunk-AISZRA4C.js.map +1 -0
  25. package/dist/chunk-J6ZTRFFW.js +64 -0
  26. package/dist/chunk-J6ZTRFFW.js.map +1 -0
  27. package/dist/chunk-LLD7LUNN.js +202 -0
  28. package/dist/chunk-LLD7LUNN.js.map +1 -0
  29. package/dist/chunk-S7PTR42P.js +19 -0
  30. package/dist/chunk-S7PTR42P.js.map +1 -0
  31. package/dist/cli/index.js +589 -0
  32. package/dist/cli/index.js.map +1 -0
  33. package/dist/inbox-MMLHISQV.js +22 -0
  34. package/dist/inbox-MMLHISQV.js.map +1 -0
  35. package/dist/index.js +2745 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/lib-FJP7J4T6.js +2281 -0
  38. package/dist/lib-FJP7J4T6.js.map +1 -0
  39. package/dist/runtime-J5NOPRBA.js +11 -0
  40. package/dist/runtime-J5NOPRBA.js.map +1 -0
  41. package/package.json +61 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../node_modules/.pnpm/@deepseek-ai+cosmokit@1.8.3/node_modules/@deepseek-ai/cosmokit/lib/index.js"],"sourcesContent":["//#region lib/types/misc.js\n/** No-op callback returning `undefined` at runtime and `any` at type level. */\nfunction noop() {}\n/** Return true when a value is `null` or `undefined`. */\nfunction isNullable(value) {\n\treturn value === null || value === void 0;\n}\n/** Return true when a value is neither `null` nor `undefined`. */\nfunction isNonNullable(value) {\n\treturn !isNullable(value);\n}\n/** Return true for non-array object values. */\nfunction isPlainObject(data) {\n\treturn data && typeof data === \"object\" && !Array.isArray(data);\n}\n/** Filter object entries and return a new object. */\nfunction filterKeys(object, filter) {\n\treturn Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));\n}\n/** Map object values while preserving the original key set. */\nfunction mapValues(object, transform) {\n\treturn Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));\n}\n/** Pick selected keys from an object, optionally including `undefined` values. */\nfunction pick(source, keys, forced) {\n\tif (!keys) return { ...source };\n\tconst result = {};\n\tfor (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];\n\treturn result;\n}\n/** Omit selected keys from a shallow object copy. */\nfunction omit(source, keys) {\n\tif (!keys) return { ...source };\n\tconst result = { ...source };\n\tfor (const key of keys) Reflect.deleteProperty(result, key);\n\treturn result;\n}\n/** Define a non-enumerable writable property and return the object. */\nfunction defineProperty(object, key, value) {\n\treturn Object.defineProperty(object, key, {\n\t\twritable: true,\n\t\tvalue,\n\t\tenumerable: false\n\t});\n}\n//#endregion\n//#region lib/types/array.js\n/** Return true when every item in `array2` is present in `array1`. */\nfunction contain(array1, array2) {\n\treturn array2.every((item) => array1.includes(item));\n}\n/** Return items that appear in both arrays. */\nfunction intersection(array1, array2) {\n\treturn array1.filter((item) => array2.includes(item));\n}\n/** Return items from `array1` that do not appear in `array2`. */\nfunction difference(array1, array2) {\n\treturn array1.filter((item) => !array2.includes(item));\n}\n/** Return the set-union of two arrays while preserving first occurrence order. */\nfunction union(array1, array2) {\n\treturn Array.from(new Set([...array1, ...array2]));\n}\n/** Remove duplicate values while preserving first occurrence order. */\nfunction deduplicate(array) {\n\treturn [...new Set(array)];\n}\n/** Remove one item from an array and report whether it was found. */\nfunction remove(list, item) {\n\tconst index = list?.indexOf(item);\n\tif (index >= 0) {\n\t\tlist.splice(index, 1);\n\t\treturn true;\n\t} else return false;\n}\n/** Normalize nullish, scalar, or array input to an array. */\nfunction makeArray(source) {\n\treturn Array.isArray(source) ? source : isNullable(source) ? [] : [source];\n}\n//#endregion\n//#region lib/types/types.js\n/** Test values using `instanceof` with a `toStringTag` fallback. */\nfunction is(type, value) {\n\tif (arguments.length === 1) return (value) => is(type, value);\n\treturn type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;\n}\nfunction isArrayBufferLike(value) {\n\treturn is(\"ArrayBuffer\", value) || is(\"SharedArrayBuffer\", value);\n}\nfunction isArrayBufferSource(value) {\n\treturn isArrayBufferLike(value) || ArrayBuffer.isView(value);\n}\n/** Binary source detection and base64/hex conversion helpers. */\nvar Binary;\n(function(Binary) {\n\tBinary.is = isArrayBufferLike;\n\tBinary.isSource = isArrayBufferSource;\n\tfunction fromSource(source) {\n\t\tif (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);\n\t\telse return source;\n\t}\n\tBinary.fromSource = fromSource;\n\tfunction toBase64(source) {\n\t\tsource = fromSource(source);\n\t\tif (typeof Buffer !== \"undefined\") return Buffer.from(source).toString(\"base64\");\n\t\tlet binary = \"\";\n\t\tconst bytes = new Uint8Array(source);\n\t\tfor (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);\n\t\treturn btoa(binary);\n\t}\n\tBinary.toBase64 = toBase64;\n\tfunction fromBase64(source) {\n\t\tif (typeof Buffer !== \"undefined\") return fromSource(Buffer.from(source, \"base64\"));\n\t\treturn Uint8Array.from(atob(source), (c) => c.charCodeAt(0));\n\t}\n\tBinary.fromBase64 = fromBase64;\n\tfunction toHex(source) {\n\t\tsource = fromSource(source);\n\t\tif (typeof Buffer !== \"undefined\") return Buffer.from(source).toString(\"hex\");\n\t\treturn Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n\t}\n\tBinary.toHex = toHex;\n\tfunction fromHex(source) {\n\t\tif (typeof Buffer !== \"undefined\") return fromSource(Buffer.from(source, \"hex\"));\n\t\tconst hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);\n\t\tconst buffer = [];\n\t\tfor (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));\n\t\treturn Uint8Array.from(buffer).buffer;\n\t}\n\tBinary.fromHex = fromHex;\n})(Binary || (Binary = {}));\n/** Decode a base64 string into binary data. */\nconst base64ToArrayBuffer = Binary.fromBase64;\n/** Encode binary data as base64. */\nconst arrayBufferToBase64 = Binary.toBase64;\n/** Decode a hex string into binary data. */\nconst hexToArrayBuffer = Binary.fromHex;\n/** Encode binary data as hex. */\nconst arrayBufferToHex = Binary.toHex;\n/** Deep-clone common JavaScript values while preserving prototypes and cycles. */\nfunction clone(source, refs = /* @__PURE__ */ new Map()) {\n\tif (!source || typeof source !== \"object\") return source;\n\tif (is(\"Date\", source)) return new Date(source.valueOf());\n\tif (is(\"RegExp\", source)) return new RegExp(source.source, source.flags);\n\tif (isArrayBufferLike(source)) return source.slice(0);\n\tif (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);\n\tconst cached = refs.get(source);\n\tif (cached) return cached;\n\tif (Array.isArray(source)) {\n\t\tconst result = [];\n\t\trefs.set(source, result);\n\t\tsource.forEach((value, index) => {\n\t\t\tresult[index] = Reflect.apply(clone, null, [value, refs]);\n\t\t});\n\t\treturn result;\n\t}\n\tconst result = Object.create(Object.getPrototypeOf(source));\n\trefs.set(source, result);\n\tfor (const key of Reflect.ownKeys(source)) {\n\t\tconst descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };\n\t\tif (\"value\" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);\n\t\tReflect.defineProperty(result, key, descriptor);\n\t}\n\treturn result;\n}\n/** Deeply compare arrays, dates, regexps, buffers, and plain object fields. */\nfunction deepEqual(a, b, strict) {\n\tif (a === b) return true;\n\tif (!strict && isNullable(a) && isNullable(b)) return true;\n\tif (typeof a !== typeof b) return false;\n\tif (typeof a !== \"object\") return false;\n\tif (!a || !b) return false;\n\tfunction check(test, then) {\n\t\treturn test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;\n\t}\n\treturn check(Array.isArray, (a, b) => a.length === b.length && a.every((item, index) => deepEqual(item, b[index]))) ?? check(is(\"Date\"), (a, b) => a.valueOf() === b.valueOf()) ?? check(is(\"RegExp\"), (a, b) => a.source === b.source && a.flags === b.flags) ?? check(isArrayBufferLike, (a, b) => {\n\t\tif (a.byteLength !== b.byteLength) return false;\n\t\tconst viewA = new Uint8Array(a);\n\t\tconst viewB = new Uint8Array(b);\n\t\tfor (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;\n\t\treturn true;\n\t}) ?? Object.keys({\n\t\t...a,\n\t\t...b\n\t}).every((key) => deepEqual(a[key], b[key], strict));\n}\n//#endregion\n//#region lib/types/string.js\n/** Uppercase the first character of a string. */\nfunction capitalize(source) {\n\treturn source.charAt(0).toUpperCase() + source.slice(1);\n}\n/** Lowercase the first character of a string. */\nfunction uncapitalize(source) {\n\treturn source.charAt(0).toLowerCase() + source.slice(1);\n}\n/** Convert dash or underscore delimited text to camelCase. */\nfunction camelCase(source) {\n\treturn source.replace(/[_-][a-z]/g, (str) => str.slice(1).toUpperCase());\n}\nfunction tokenize(source, delimiters, delimiter) {\n\tconst output = [];\n\tlet state = 0;\n\tfor (let i = 0; i < source.length; i++) {\n\t\tconst code = source.charCodeAt(i);\n\t\tif (code >= 65 && code <= 90) {\n\t\t\tif (state === 1) {\n\t\t\t\tconst next = source.charCodeAt(i + 1);\n\t\t\t\tif (next >= 97 && next <= 122) output.push(delimiter);\n\t\t\t\toutput.push(code + 32);\n\t\t\t} else {\n\t\t\t\tif (state !== 0) output.push(delimiter);\n\t\t\t\toutput.push(code + 32);\n\t\t\t}\n\t\t\tstate = 1;\n\t\t} else if (code >= 97 && code <= 122) {\n\t\t\toutput.push(code);\n\t\t\tstate = 2;\n\t\t} else if (delimiters.includes(code)) {\n\t\t\tif (state !== 0) output.push(delimiter);\n\t\t\tstate = 0;\n\t\t} else output.push(code);\n\t}\n\treturn String.fromCharCode(...output);\n}\n/** Convert text to dash-delimited parameter case. */\nfunction paramCase(source) {\n\treturn tokenize(source, [45, 95], 45);\n}\n/** Convert text to underscore-delimited snake case. */\nfunction snakeCase(source) {\n\treturn tokenize(source, [45, 95], 95);\n}\n/** Runtime alias for `camelCase`. */\nconst camelize = camelCase;\n/** Runtime alias for `paramCase`. */\nconst hyphenate = paramCase;\n/** Format a property key as a JavaScript member access suffix. */\nfunction formatProperty(key) {\n\tif (typeof key !== \"string\") return `[${key.toString()}]`;\n\treturn /^[a-z_$][\\w$]*$/i.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;\n}\n/** Remove one trailing slash from a path string. */\nfunction trimSlash(source) {\n\treturn source.replace(/\\/$/, \"\");\n}\n/** Ensure a path starts with `/` and has no trailing slash. */\nfunction sanitize(source) {\n\tif (!source.startsWith(\"/\")) source = \"/\" + source;\n\treturn trimSlash(source);\n}\n//#endregion\n//#region lib/types/time.js\n/** Time constants plus parsing and formatting helpers. */\nvar Time;\n(function(Time) {\n\tTime.millisecond = 1;\n\tTime.second = 1e3;\n\tTime.minute = Time.second * 60;\n\tTime.hour = Time.minute * 60;\n\tTime.day = Time.hour * 24;\n\tTime.week = Time.day * 7;\n\tlet timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();\n\tfunction setTimezoneOffset(offset) {\n\t\ttimezoneOffset = offset;\n\t}\n\tTime.setTimezoneOffset = setTimezoneOffset;\n\tfunction getTimezoneOffset() {\n\t\treturn timezoneOffset;\n\t}\n\tTime.getTimezoneOffset = getTimezoneOffset;\n\tfunction getDateNumber(date = /* @__PURE__ */ new Date(), offset) {\n\t\tif (typeof date === \"number\") date = new Date(date);\n\t\tif (offset === void 0) offset = timezoneOffset;\n\t\treturn Math.floor((date.valueOf() / Time.minute - offset) / 1440);\n\t}\n\tTime.getDateNumber = getDateNumber;\n\tfunction fromDateNumber(value, offset) {\n\t\tconst date = new Date(value * Time.day);\n\t\tif (offset === void 0) offset = timezoneOffset;\n\t\treturn new Date(+date + offset * Time.minute);\n\t}\n\tTime.fromDateNumber = fromDateNumber;\n\tconst numeric = /\\d+(?:\\.\\d+)?/.source;\n\tconst timeRegExp = new RegExp(`^${[\n\t\t\"w(?:eek(?:s)?)?\",\n\t\t\"d(?:ay(?:s)?)?\",\n\t\t\"h(?:our(?:s)?)?\",\n\t\t\"m(?:in(?:ute)?(?:s)?)?\",\n\t\t\"s(?:ec(?:ond)?(?:s)?)?\"\n\t].map((unit) => `(${numeric}${unit})?`).join(\"\")}$`);\n\tfunction parseTime(source) {\n\t\tconst capture = timeRegExp.exec(source);\n\t\tif (!capture) return 0;\n\t\treturn (parseFloat(capture[1]) * Time.week || 0) + (parseFloat(capture[2]) * Time.day || 0) + (parseFloat(capture[3]) * Time.hour || 0) + (parseFloat(capture[4]) * Time.minute || 0) + (parseFloat(capture[5]) * Time.second || 0);\n\t}\n\tTime.parseTime = parseTime;\n\tfunction parseDate(date) {\n\t\tconst parsed = parseTime(date);\n\t\tif (parsed) date = Date.now() + parsed;\n\t\telse if (/^\\d{1,2}(:\\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;\n\t\telse if (/^\\d{1,2}-\\d{1,2}-\\d{1,2}(:\\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;\n\t\treturn date ? new Date(date) : /* @__PURE__ */ new Date();\n\t}\n\tTime.parseDate = parseDate;\n\tfunction format(ms) {\n\t\tconst abs = Math.abs(ms);\n\t\tif (abs >= Time.day - Time.hour / 2) return Math.round(ms / Time.day) + \"d\";\n\t\telse if (abs >= Time.hour - Time.minute / 2) return Math.round(ms / Time.hour) + \"h\";\n\t\telse if (abs >= Time.minute - Time.second / 2) return Math.round(ms / Time.minute) + \"m\";\n\t\telse if (abs >= Time.second) return Math.round(ms / Time.second) + \"s\";\n\t\treturn ms + \"ms\";\n\t}\n\tTime.format = format;\n\tfunction toDigits(source, length = 2) {\n\t\treturn source.toString().padStart(length, \"0\");\n\t}\n\tTime.toDigits = toDigits;\n\tfunction template(template, time = /* @__PURE__ */ new Date()) {\n\t\treturn template.replace(\"yyyy\", time.getFullYear().toString()).replace(\"yy\", time.getFullYear().toString().slice(2)).replace(\"MM\", toDigits(time.getMonth() + 1)).replace(\"dd\", toDigits(time.getDate())).replace(\"hh\", toDigits(time.getHours())).replace(\"mm\", toDigits(time.getMinutes())).replace(\"ss\", toDigits(time.getSeconds())).replace(\"SSS\", toDigits(time.getMilliseconds(), 3));\n\t}\n\tTime.template = template;\n})(Time || (Time = {}));\n//#endregion\nexport { Binary, Time, arrayBufferToBase64, arrayBufferToHex, base64ToArrayBuffer, camelCase, camelize, capitalize, clone, contain, deduplicate, deepEqual, defineProperty, difference, filterKeys, formatProperty, hexToArrayBuffer, hyphenate, intersection, is, isNonNullable, isNullable, isPlainObject, makeArray, mapValues, mapValues as valueMap, noop, omit, paramCase, pick, remove, sanitize, snakeCase, trimSlash, uncapitalize, union };\n"],"mappings":"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","names":["value","Binary","result","a","b","Time","template"]}
@@ -0,0 +1,64 @@
1
+ // src/core/bindings.ts
2
+ import fs from "fs";
3
+ import path from "path";
4
+ function bindingsFilePath(settingsDir) {
5
+ return path.join(settingsDir, "bindings.json");
6
+ }
7
+ function loadBindings(guard, settingsDir) {
8
+ const file = bindingsFilePath(settingsDir);
9
+ try {
10
+ const raw = JSON.parse(fs.readFileSync(guard.assert(file), "utf8"));
11
+ return { bindings: Array.isArray(raw.bindings) ? raw.bindings : [] };
12
+ } catch {
13
+ return { bindings: [] };
14
+ }
15
+ }
16
+ function saveBindings(guard, settingsDir, data) {
17
+ const file = guard.assert(bindingsFilePath(settingsDir));
18
+ fs.mkdirSync(path.dirname(file), { recursive: true });
19
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), "utf8");
20
+ }
21
+ function addBinding(guard, settingsDir, sessionId, opts = {}) {
22
+ const data = loadBindings(guard, settingsDir);
23
+ const existing = data.bindings.find((b) => b.sessionId === sessionId);
24
+ if (existing) {
25
+ existing.deliver = opts.deliver ?? existing.deliver;
26
+ existing.observe = opts.observe ?? existing.observe;
27
+ saveBindings(guard, settingsDir, data);
28
+ return existing;
29
+ }
30
+ const binding = {
31
+ sessionId,
32
+ deliver: opts.deliver ?? true,
33
+ observe: opts.observe ?? false,
34
+ addedAt: (/* @__PURE__ */ new Date()).toISOString()
35
+ };
36
+ data.bindings.push(binding);
37
+ saveBindings(guard, settingsDir, data);
38
+ return binding;
39
+ }
40
+ function removeBinding(guard, settingsDir, sessionId) {
41
+ const data = loadBindings(guard, settingsDir);
42
+ const before = data.bindings.length;
43
+ data.bindings = data.bindings.filter((b) => b.sessionId !== sessionId);
44
+ if (data.bindings.length === before) return false;
45
+ saveBindings(guard, settingsDir, data);
46
+ return true;
47
+ }
48
+ function deliverTargets(data) {
49
+ return data.bindings.filter((b) => b.deliver);
50
+ }
51
+ function observeTargets(data) {
52
+ return data.bindings.filter((b) => b.observe);
53
+ }
54
+
55
+ export {
56
+ bindingsFilePath,
57
+ loadBindings,
58
+ saveBindings,
59
+ addBinding,
60
+ removeBinding,
61
+ deliverTargets,
62
+ observeTargets
63
+ };
64
+ //# sourceMappingURL=chunk-J6ZTRFFW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/bindings.ts"],"sourcesContent":["// Session bindings (design doc D13): binding = ①被心跳观察对话事件(inbox\n// 来源)+ ②主动消息投递目标。Canonical storage: data/settings/bindings.json\n// (user layer - survives uninstall/reinstall, D15). Edited via CLI or hand.\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { PathGuard } from './path-guard.js';\n\nexport interface SessionBinding {\n sessionId: string;\n /** Deliver heartbeat expressions into this session's inbox (live only). */\n deliver: boolean;\n /** Observe this session's new user messages into the profile inbox. */\n observe: boolean;\n addedAt: string;\n}\n\nexport interface BindingsFile {\n bindings: SessionBinding[];\n}\n\nexport function bindingsFilePath(settingsDir: string): string {\n return path.join(settingsDir, 'bindings.json');\n}\n\nexport function loadBindings(guard: PathGuard, settingsDir: string): BindingsFile {\n const file = bindingsFilePath(settingsDir);\n try {\n const raw = JSON.parse(fs.readFileSync(guard.assert(file), 'utf8')) as BindingsFile;\n return { bindings: Array.isArray(raw.bindings) ? raw.bindings : [] };\n } catch {\n return { bindings: [] };\n }\n}\n\nexport function saveBindings(guard: PathGuard, settingsDir: string, data: BindingsFile): void {\n const file = guard.assert(bindingsFilePath(settingsDir));\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf8');\n}\n\nexport function addBinding(\n guard: PathGuard,\n settingsDir: string,\n sessionId: string,\n opts: { deliver?: boolean; observe?: boolean } = {},\n): SessionBinding {\n const data = loadBindings(guard, settingsDir);\n const existing = data.bindings.find((b) => b.sessionId === sessionId);\n if (existing) {\n existing.deliver = opts.deliver ?? existing.deliver;\n existing.observe = opts.observe ?? existing.observe;\n saveBindings(guard, settingsDir, data);\n return existing;\n }\n const binding: SessionBinding = {\n sessionId,\n deliver: opts.deliver ?? true,\n observe: opts.observe ?? false,\n addedAt: new Date().toISOString(),\n };\n data.bindings.push(binding);\n saveBindings(guard, settingsDir, data);\n return binding;\n}\n\nexport function removeBinding(guard: PathGuard, settingsDir: string, sessionId: string): boolean {\n const data = loadBindings(guard, settingsDir);\n const before = data.bindings.length;\n data.bindings = data.bindings.filter((b) => b.sessionId !== sessionId);\n if (data.bindings.length === before) return false;\n saveBindings(guard, settingsDir, data);\n return true;\n}\n\nexport function deliverTargets(data: BindingsFile): SessionBinding[] {\n return data.bindings.filter((b) => b.deliver);\n}\n\nexport function observeTargets(data: BindingsFile): SessionBinding[] {\n return data.bindings.filter((b) => b.observe);\n}\n"],"mappings":";AAIA,OAAO,QAAQ;AACf,OAAO,UAAU;AAgBV,SAAS,iBAAiB,aAA6B;AAC5D,SAAO,KAAK,KAAK,aAAa,eAAe;AAC/C;AAEO,SAAS,aAAa,OAAkB,aAAmC;AAChF,QAAM,OAAO,iBAAiB,WAAW;AACzC,MAAI;AACF,UAAM,MAAM,KAAK,MAAM,GAAG,aAAa,MAAM,OAAO,IAAI,GAAG,MAAM,CAAC;AAClE,WAAO,EAAE,UAAU,MAAM,QAAQ,IAAI,QAAQ,IAAI,IAAI,WAAW,CAAC,EAAE;AAAA,EACrE,QAAQ;AACN,WAAO,EAAE,UAAU,CAAC,EAAE;AAAA,EACxB;AACF;AAEO,SAAS,aAAa,OAAkB,aAAqB,MAA0B;AAC5F,QAAM,OAAO,MAAM,OAAO,iBAAiB,WAAW,CAAC;AACvD,KAAG,UAAU,KAAK,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACpD,KAAG,cAAc,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,MAAM;AAC9D;AAEO,SAAS,WACd,OACA,aACA,WACA,OAAiD,CAAC,GAClC;AAChB,QAAM,OAAO,aAAa,OAAO,WAAW;AAC5C,QAAM,WAAW,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS;AACpE,MAAI,UAAU;AACZ,aAAS,UAAU,KAAK,WAAW,SAAS;AAC5C,aAAS,UAAU,KAAK,WAAW,SAAS;AAC5C,iBAAa,OAAO,aAAa,IAAI;AACrC,WAAO;AAAA,EACT;AACA,QAAM,UAA0B;AAAA,IAC9B;AAAA,IACA,SAAS,KAAK,WAAW;AAAA,IACzB,SAAS,KAAK,WAAW;AAAA,IACzB,UAAS,oBAAI,KAAK,GAAE,YAAY;AAAA,EAClC;AACA,OAAK,SAAS,KAAK,OAAO;AAC1B,eAAa,OAAO,aAAa,IAAI;AACrC,SAAO;AACT;AAEO,SAAS,cAAc,OAAkB,aAAqB,WAA4B;AAC/F,QAAM,OAAO,aAAa,OAAO,WAAW;AAC5C,QAAM,SAAS,KAAK,SAAS;AAC7B,OAAK,WAAW,KAAK,SAAS,OAAO,CAAC,MAAM,EAAE,cAAc,SAAS;AACrE,MAAI,KAAK,SAAS,WAAW,OAAQ,QAAO;AAC5C,eAAa,OAAO,aAAa,IAAI;AACrC,SAAO;AACT;AAEO,SAAS,eAAe,MAAsC;AACnE,SAAO,KAAK,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO;AAC9C;AAEO,SAAS,eAAe,MAAsC;AACnE,SAAO,KAAK,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO;AAC9C;","names":[]}
@@ -0,0 +1,202 @@
1
+ // src/core/paths.ts
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ var resolved = null;
6
+ function findPackageRoot(startFile) {
7
+ let dir = path.dirname(path.resolve(startFile));
8
+ for (; ; ) {
9
+ if (fs.existsSync(path.join(dir, "package.json"))) return dir;
10
+ const parent = path.dirname(dir);
11
+ if (parent === dir) throw new Error("package.json not found above " + startFile);
12
+ dir = parent;
13
+ }
14
+ }
15
+ function packageRoot() {
16
+ return findPackageRoot(fileURLToPath(import.meta.url));
17
+ }
18
+ function initWorkspace(config = {}) {
19
+ if (resolved) return resolved;
20
+ const root = packageRoot();
21
+ const dataDir = path.resolve(
22
+ process.env.HEARTBEAT_DATA_DIR || config.dataDir || path.join(root, "data")
23
+ );
24
+ const paths = {
25
+ dataDir,
26
+ settingsDir: path.join(dataDir, "settings"),
27
+ logsDir: path.join(dataDir, "logs"),
28
+ tmpDir: path.join(dataDir, "tmp"),
29
+ exportsDir: path.join(dataDir, "exports"),
30
+ packageRoot: root,
31
+ configDir: path.join(root, "config"),
32
+ assetsDir: path.join(root, "assets")
33
+ };
34
+ for (const dir of [
35
+ paths.dataDir,
36
+ paths.settingsDir,
37
+ paths.logsDir,
38
+ paths.tmpDir,
39
+ paths.exportsDir
40
+ ]) {
41
+ fs.mkdirSync(dir, { recursive: true });
42
+ }
43
+ resolved = paths;
44
+ return paths;
45
+ }
46
+ function workspace() {
47
+ if (!resolved) throw new Error("workspace not initialized: call initWorkspace() first");
48
+ return resolved;
49
+ }
50
+
51
+ // src/vault/vault.ts
52
+ import fs2 from "fs";
53
+ import path2 from "path";
54
+ import { spawnSync } from "child_process";
55
+ import { randomUUID } from "crypto";
56
+ var MAGIC = Buffer.from("KHBV1", "ascii");
57
+ var VAULT_TIMEOUT_MS = 3e4;
58
+ var cachedScriptPath = null;
59
+ function vaultScriptPath() {
60
+ if (cachedScriptPath) return cachedScriptPath;
61
+ const script = path2.join(workspace().assetsDir, "vault.ps1");
62
+ if (!fs2.existsSync(script)) throw new Error(`vault script missing: ${script}`);
63
+ cachedScriptPath = script;
64
+ return script;
65
+ }
66
+ function tmpPlainName(target) {
67
+ return path2.join(workspace().tmpDir, `.${path2.basename(target)}.${randomUUID().slice(0, 8)}.plain`);
68
+ }
69
+ function tmpEncName(target) {
70
+ return path2.join(workspace().tmpDir, `.${path2.basename(target)}.${randomUUID().slice(0, 8)}.enc`);
71
+ }
72
+ function runVault(guard, args) {
73
+ const r = spawnSync(
74
+ "powershell.exe",
75
+ ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", vaultScriptPath(), ...args],
76
+ { timeout: VAULT_TIMEOUT_MS, encoding: "utf8" }
77
+ );
78
+ if (r.error) throw new Error(`vault spawn failed: ${String(r.error)}`);
79
+ if (r.status !== 0) {
80
+ const detail = (r.stderr || r.stdout || "").trim().split("\n").slice(-3).join("; ");
81
+ throw new Error(`vault ${args[0]} failed (exit ${r.status}): ${detail}`);
82
+ }
83
+ }
84
+ function isEncrypted(file) {
85
+ if (!fs2.existsSync(file)) return false;
86
+ const fd = fs2.openSync(file, "r");
87
+ try {
88
+ const hdr = Buffer.alloc(MAGIC.length);
89
+ const read = fs2.readSync(fd, hdr, 0, hdr.length, 0);
90
+ return read === MAGIC.length && hdr.equals(MAGIC);
91
+ } finally {
92
+ fs2.closeSync(fd);
93
+ }
94
+ }
95
+ function loadJson(guard, file) {
96
+ const f = guard.assert(file);
97
+ if (!fs2.existsSync(f)) return null;
98
+ if (!isEncrypted(f)) {
99
+ try {
100
+ return JSON.parse(fs2.readFileSync(f, "utf8"));
101
+ } catch {
102
+ return null;
103
+ }
104
+ }
105
+ const tmp = tmpPlainName(f);
106
+ try {
107
+ runVault(guard, ["unprotect", "-InFile", f, "-OutFile", tmp]);
108
+ return JSON.parse(fs2.readFileSync(tmp, "utf8"));
109
+ } finally {
110
+ fs2.rmSync(tmp, { force: true });
111
+ }
112
+ }
113
+ function saveJson(guard, file, value) {
114
+ const f = guard.assert(file);
115
+ fs2.mkdirSync(path2.dirname(f), { recursive: true });
116
+ const plain = tmpPlainName(f);
117
+ const enc = tmpEncName(f);
118
+ try {
119
+ fs2.writeFileSync(plain, JSON.stringify(value, null, 2), "utf8");
120
+ runVault(guard, ["protect", "-InFile", plain, "-OutFile", enc]);
121
+ fs2.renameSync(enc, f);
122
+ } finally {
123
+ fs2.rmSync(plain, { force: true });
124
+ fs2.rmSync(enc, { force: true });
125
+ }
126
+ }
127
+ function readText(guard, file, fallback = "") {
128
+ const f = guard.assert(file);
129
+ try {
130
+ return fs2.readFileSync(f, "utf8");
131
+ } catch {
132
+ return fallback;
133
+ }
134
+ }
135
+ function writeText(guard, file, content) {
136
+ const f = guard.assert(file);
137
+ fs2.mkdirSync(path2.dirname(f), { recursive: true });
138
+ const tmp = tmpPlainName(f);
139
+ try {
140
+ fs2.writeFileSync(tmp, content, "utf8");
141
+ fs2.renameSync(tmp, f);
142
+ } finally {
143
+ fs2.rmSync(tmp, { force: true });
144
+ }
145
+ }
146
+ function loadEncryptedText(guard, file) {
147
+ const f = guard.assert(file);
148
+ if (!fs2.existsSync(f)) return null;
149
+ if (!isEncrypted(f)) return fs2.readFileSync(f, "utf8");
150
+ const tmp = tmpPlainName(f);
151
+ try {
152
+ runVault(guard, ["unprotect", "-InFile", f, "-OutFile", tmp]);
153
+ return fs2.readFileSync(tmp, "utf8");
154
+ } finally {
155
+ fs2.rmSync(tmp, { force: true });
156
+ }
157
+ }
158
+ function saveEncryptedText(guard, file, content) {
159
+ const f = guard.assert(file);
160
+ fs2.mkdirSync(path2.dirname(f), { recursive: true });
161
+ const plain = tmpPlainName(f);
162
+ const enc = tmpEncName(f);
163
+ try {
164
+ fs2.writeFileSync(plain, content, "utf8");
165
+ runVault(guard, ["protect", "-InFile", plain, "-OutFile", enc]);
166
+ fs2.renameSync(enc, f);
167
+ } finally {
168
+ fs2.rmSync(plain, { force: true });
169
+ fs2.rmSync(enc, { force: true });
170
+ }
171
+ }
172
+ function encryptFile(guard, inFile, outFile) {
173
+ const inPath = guard.assert(inFile);
174
+ const outPath = guard.assert(outFile);
175
+ fs2.mkdirSync(path2.dirname(outPath), { recursive: true });
176
+ const enc = tmpEncName(outPath);
177
+ try {
178
+ runVault(guard, ["protect", "-InFile", inPath, "-OutFile", enc]);
179
+ fs2.renameSync(enc, outPath);
180
+ } finally {
181
+ fs2.rmSync(enc, { force: true });
182
+ }
183
+ }
184
+ function decryptFile(guard, inFile, outFile) {
185
+ const inPath = guard.assert(inFile);
186
+ const outPath = guard.assert(outFile);
187
+ fs2.mkdirSync(path2.dirname(outPath), { recursive: true });
188
+ runVault(guard, ["unprotect", "-InFile", inPath, "-OutFile", outPath]);
189
+ }
190
+
191
+ export {
192
+ initWorkspace,
193
+ loadJson,
194
+ saveJson,
195
+ readText,
196
+ writeText,
197
+ loadEncryptedText,
198
+ saveEncryptedText,
199
+ encryptFile,
200
+ decryptFile
201
+ };
202
+ //# sourceMappingURL=chunk-LLD7LUNN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/paths.ts","../src/vault/vault.ts"],"sourcesContent":["// Workspace/data directory resolution and package asset location.\n//\n// The data dir is the ONLY directory the plugin writes to at runtime\n// (requirement 8). Resolution order: env override > plugin config > default\n// (packageRoot/data). All fs writes must go through the path guard created\n// from this dir (see core/path-guard.ts).\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport interface WorkspacePaths {\n /** Guard boundary and the only writable tree at runtime. */\n dataDir: string;\n settingsDir: string;\n logsDir: string;\n tmpDir: string;\n exportsDir: string;\n /** Package root (where package.json lives). Read-only at runtime. */\n packageRoot: string;\n configDir: string;\n assetsDir: string;\n}\n\nexport interface WorkspaceConfigInput {\n dataDir?: string | null;\n}\n\nlet resolved: WorkspacePaths | null = null;\n\n/** Walk up from a module file to the directory containing package.json. */\nexport function findPackageRoot(startFile: string): string {\n let dir = path.dirname(path.resolve(startFile));\n for (;;) {\n if (fs.existsSync(path.join(dir, 'package.json'))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) throw new Error('package.json not found above ' + startFile);\n dir = parent;\n }\n}\n\nexport function packageRoot(): string {\n return findPackageRoot(fileURLToPath(import.meta.url));\n}\n\n/**\n * Resolve and create the workspace layout. Idempotent; must be called once\n * from the plugin entry before any fs write happens.\n */\nexport function initWorkspace(config: WorkspaceConfigInput = {}): WorkspacePaths {\n if (resolved) return resolved;\n const root = packageRoot();\n const dataDir = path.resolve(\n process.env.HEARTBEAT_DATA_DIR || config.dataDir || path.join(root, 'data'),\n );\n const paths: WorkspacePaths = {\n dataDir,\n settingsDir: path.join(dataDir, 'settings'),\n logsDir: path.join(dataDir, 'logs'),\n tmpDir: path.join(dataDir, 'tmp'),\n exportsDir: path.join(dataDir, 'exports'),\n packageRoot: root,\n configDir: path.join(root, 'config'),\n assetsDir: path.join(root, 'assets'),\n };\n // Bootstrap creation happens before the guard exists; creating exactly one\n // directory tree at a known location is the safe window for this.\n for (const dir of [\n paths.dataDir,\n paths.settingsDir,\n paths.logsDir,\n paths.tmpDir,\n paths.exportsDir,\n ]) {\n fs.mkdirSync(dir, { recursive: true });\n }\n resolved = paths;\n return paths;\n}\n\n/** Access already-initialized paths. Throws if initWorkspace was not called. */\nexport function workspace(): WorkspacePaths {\n if (!resolved) throw new Error('workspace not initialized: call initWorkspace() first');\n return resolved;\n}\n\n/** Test-only: forget the resolved singleton so a later init re-resolves. */\nexport function resetWorkspaceForTest(): void {\n resolved = null;\n}\n","// Transparent encryption read/write layer (port of v1 lib/vault.mjs).\n//\n// Mechanism: Node <-> vault.ps1 hand off through temp files (plain text\n// windows are millisecond-scale). v2 hardening over v1:\n// - plaintext temp files live ONLY under data/tmp (never beside targets);\n// - every path passes the workspace guard before reaching PowerShell;\n// - encrypted output lands via same-volume rename (atomic replace).\n// Encryption failure is fail-closed: throw, never fall back to plaintext.\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { spawnSync } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport type { PathGuard } from '../core/path-guard.js';\nimport { workspace } from '../core/paths.js';\n\nconst MAGIC = Buffer.from('KHBV1', 'ascii');\nconst VAULT_TIMEOUT_MS = 30_000;\n\nlet cachedScriptPath: string | null = null;\n\nfunction vaultScriptPath(): string {\n if (cachedScriptPath) return cachedScriptPath;\n const script = path.join(workspace().assetsDir, 'vault.ps1');\n if (!fs.existsSync(script)) throw new Error(`vault script missing: ${script}`);\n cachedScriptPath = script;\n return script;\n}\n\nfunction tmpPlainName(target: string): string {\n return path.join(workspace().tmpDir, `.${path.basename(target)}.${randomUUID().slice(0, 8)}.plain`);\n}\n\nfunction tmpEncName(target: string): string {\n return path.join(workspace().tmpDir, `.${path.basename(target)}.${randomUUID().slice(0, 8)}.enc`);\n}\n\nfunction runVault(guard: PathGuard, args: string[]): void {\n const r = spawnSync(\n 'powershell.exe',\n ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', vaultScriptPath(), ...args],\n { timeout: VAULT_TIMEOUT_MS, encoding: 'utf8' },\n );\n if (r.error) throw new Error(`vault spawn failed: ${String(r.error)}`);\n if (r.status !== 0) {\n const detail = (r.stderr || r.stdout || '').trim().split('\\n').slice(-3).join('; ');\n throw new Error(`vault ${args[0]} failed (exit ${r.status}): ${detail}`);\n }\n}\n\n/** KHBV1 header check without reading the whole file. */\nexport function isEncrypted(file: string): boolean {\n if (!fs.existsSync(file)) return false;\n const fd = fs.openSync(file, 'r');\n try {\n const hdr = Buffer.alloc(MAGIC.length);\n const read = fs.readSync(fd, hdr, 0, hdr.length, 0);\n return read === MAGIC.length && hdr.equals(MAGIC);\n } finally {\n fs.closeSync(fd);\n }\n}\n\n/**\n * Read JSON: encrypted files are decrypted to a data/tmp plaintext window\n * that is shredded immediately after parse; plaintext stays compatible.\n */\nexport function loadJson<T>(guard: PathGuard, file: string): T | null {\n const f = guard.assert(file);\n if (!fs.existsSync(f)) return null;\n if (!isEncrypted(f)) {\n try {\n return JSON.parse(fs.readFileSync(f, 'utf8')) as T;\n } catch {\n return null;\n }\n }\n const tmp = tmpPlainName(f);\n try {\n runVault(guard, ['unprotect', '-InFile', f, '-OutFile', tmp]);\n return JSON.parse(fs.readFileSync(tmp, 'utf8')) as T;\n } finally {\n fs.rmSync(tmp, { force: true });\n }\n}\n\n/** Write JSON: plaintext window in data/tmp -> DPAPI encrypt -> atomic rename into place. */\nexport function saveJson(guard: PathGuard, file: string, value: unknown): void {\n const f = guard.assert(file);\n fs.mkdirSync(path.dirname(f), { recursive: true });\n const plain = tmpPlainName(f);\n const enc = tmpEncName(f);\n try {\n fs.writeFileSync(plain, JSON.stringify(value, null, 2), 'utf8');\n runVault(guard, ['protect', '-InFile', plain, '-OutFile', enc]);\n fs.renameSync(enc, f);\n } finally {\n fs.rmSync(plain, { force: true });\n fs.rmSync(enc, { force: true });\n }\n}\n\n/** Read a plaintext UTF-8 text file (ledger etc.), with fallback. */\nexport function readText(guard: PathGuard, file: string, fallback = ''): string {\n const f = guard.assert(file);\n try {\n return fs.readFileSync(f, 'utf8');\n } catch {\n return fallback;\n }\n}\n\n/** Write a plaintext UTF-8 text file atomically (ledger etc.). */\nexport function writeText(guard: PathGuard, file: string, content: string): void {\n const f = guard.assert(file);\n fs.mkdirSync(path.dirname(f), { recursive: true });\n const tmp = tmpPlainName(f);\n try {\n fs.writeFileSync(tmp, content, 'utf8');\n fs.renameSync(tmp, f);\n } finally {\n fs.rmSync(tmp, { force: true });\n }\n}\n\n/** Read an encrypted UTF-8 text file (e.g. seeds.jsonl). Missing -> null. */\nexport function loadEncryptedText(guard: PathGuard, file: string): string | null {\n const f = guard.assert(file);\n if (!fs.existsSync(f)) return null;\n if (!isEncrypted(f)) return fs.readFileSync(f, 'utf8');\n const tmp = tmpPlainName(f);\n try {\n runVault(guard, ['unprotect', '-InFile', f, '-OutFile', tmp]);\n return fs.readFileSync(tmp, 'utf8');\n } finally {\n fs.rmSync(tmp, { force: true });\n }\n}\n\n/** Write an encrypted UTF-8 text file atomically. */\nexport function saveEncryptedText(guard: PathGuard, file: string, content: string): void {\n const f = guard.assert(file);\n fs.mkdirSync(path.dirname(f), { recursive: true });\n const plain = tmpPlainName(f);\n const enc = tmpEncName(f);\n try {\n fs.writeFileSync(plain, content, 'utf8');\n runVault(guard, ['protect', '-InFile', plain, '-OutFile', enc]);\n fs.renameSync(enc, f);\n } finally {\n fs.rmSync(plain, { force: true });\n fs.rmSync(enc, { force: true });\n }\n}\n\n/** Encrypt any binary file (e.g. screenshot): inFile -> encrypted outFile. */\nexport function encryptFile(guard: PathGuard, inFile: string, outFile: string): void {\n const inPath = guard.assert(inFile);\n const outPath = guard.assert(outFile);\n fs.mkdirSync(path.dirname(outPath), { recursive: true });\n const enc = tmpEncName(outPath);\n try {\n runVault(guard, ['protect', '-InFile', inPath, '-OutFile', enc]);\n fs.renameSync(enc, outPath);\n } finally {\n fs.rmSync(enc, { force: true });\n }\n}\n\n/**\n * Decrypt an encrypted file to a plaintext output (caller must place the\n * output under data/tmp and delete it after use; \"use then burn\" discipline).\n */\nexport function decryptFile(guard: PathGuard, inFile: string, outFile: string): void {\n const inPath = guard.assert(inFile);\n const outPath = guard.assert(outFile);\n fs.mkdirSync(path.dirname(outPath), { recursive: true });\n runVault(guard, ['unprotect', '-InFile', inPath, '-OutFile', outPath]);\n}\n"],"mappings":"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","names":["fs","path","path","fs"]}
@@ -0,0 +1,19 @@
1
+ // src/core/runtime.ts
2
+ var runtime = null;
3
+ function setRuntime(r) {
4
+ runtime = r;
5
+ }
6
+ function getRuntime() {
7
+ if (!runtime) throw new Error("heartbeat runtime not initialized");
8
+ return runtime;
9
+ }
10
+ function resetRuntimeForTest() {
11
+ runtime = null;
12
+ }
13
+
14
+ export {
15
+ setRuntime,
16
+ getRuntime,
17
+ resetRuntimeForTest
18
+ };
19
+ //# sourceMappingURL=chunk-S7PTR42P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/runtime.ts"],"sourcesContent":["// Runtime singleton shared by all modules after the plugin entry initializes.\n\nimport type { PathGuard } from './path-guard.js';\nimport type { WorkspacePaths } from './paths.js';\nimport type { Policy } from '../config/schema.js';\n\nexport interface HeartbeatRuntime {\n paths: WorkspacePaths;\n guard: PathGuard;\n policy: Policy;\n /** Live UI flags (M7): re-read by the RPC status endpoint for the card. */\n flags: {\n statusbarEnabled(): boolean;\n timeInjectMin(): number;\n };\n}\n\nlet runtime: HeartbeatRuntime | null = null;\n\nexport function setRuntime(r: HeartbeatRuntime): void {\n runtime = r;\n}\n\nexport function getRuntime(): HeartbeatRuntime {\n if (!runtime) throw new Error('heartbeat runtime not initialized');\n return runtime;\n}\n\nexport function resetRuntimeForTest(): void {\n runtime = null;\n}\n"],"mappings":";AAiBA,IAAI,UAAmC;AAEhC,SAAS,WAAW,GAA2B;AACpD,YAAU;AACZ;AAEO,SAAS,aAA+B;AAC7C,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,mCAAmC;AACjE,SAAO;AACT;AAEO,SAAS,sBAA4B;AAC1C,YAAU;AACZ;","names":[]}