clawvault
by Versatly · v1.5.1
Structured memory system for OpenClaw agents. Context death resilience (checkpoint/recover), structured storage, Obsidian-compatible markdown, local semantic search, and session transcript repair.
Discussion
Sign in to join the discussion.
Scan Report
Scanners5/5 ran
clawguard-rules▸1 finding2ms
View logs
1[2026-02-13T00:34:00.110Z] Running @yourclaw/clawguard-rules pattern matcher2Scanning: /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/SKILL.md3Content length: 5947 chars4Patterns matched: 15 [critical] MAL-006: Persistence mechanism installation6✓ Completed in 2ms
gitleaks▸0 findings152448ms
View logs
1[2026-02-13T00:36:32.558Z] $ gitleaks detect --source /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1 --report-format json --report-path /dev/stdout --no-git23⚠ stderr output:4○5 │╲6 │ ○7 ○ ░8 ░ gitleaks910[90m12:36AM[0m [31mFTL[0m [1mReport path is not writable: /dev/stdout[0m [36merror=[0m[31m[1m"open /dev/stdout: no such device or address"[0m[0m1112Process exited with code 113✓ Completed in 152448ms
semgrep▸87 findings215536ms
View logs
1[2026-02-13T00:37:35.649Z] $ semgrep scan --json --quiet --config auto /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-12{"version":"1.151.0","results":[{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":38,"col":46,"offset":896},"end":{"line":38,"col":55,"offset":905},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":63,"col":25,"offset":1540},"end":{"line":63,"col":34,"offset":1549},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":119,"col":77,"offset":3284},"end":{"line":119,"col":87,"offset":3294},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":123,"col":58,"offset":3430},"end":{"line":123,"col":68,"offset":3440},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js","start":{"line":30,"col":33,"offset":1020},"end":{"line":30,"col":42,"offset":1029},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js","start":{"line":44,"col":32,"offset":1333},"end":{"line":44,"col":40,"offset":1341},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":47,"col":25,"offset":1132},"end":{"line":47,"col":34,"offset":1141},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":55,"col":36,"offset":1362},"end":{"line":55,"col":39,"offset":1365},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":58,"col":30,"offset":1482},"end":{"line":58,"col":33,"offset":1485},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":69,"col":38,"offset":1836},"end":{"line":69,"col":41,"offset":1839},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":164,"col":30,"offset":4729},"end":{"line":164,"col":39,"offset":4738},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":180,"col":25,"offset":5181},"end":{"line":180,"col":34,"offset":5190},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":181,"col":30,"offset":5237},"end":{"line":181,"col":33,"offset":5240},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":182,"col":36,"offset":5296},"end":{"line":182,"col":39,"offset":5299},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":204,"col":38,"offset":5957},"end":{"line":204,"col":41,"offset":5960},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.test.ts","start":{"line":89,"col":48,"offset":2019},"end":{"line":89,"col":54,"offset":2025},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.ts","start":{"line":39,"col":36,"offset":1092},"end":{"line":39,"col":45,"offset":1101},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.ts","start":{"line":80,"col":46,"offset":2414},"end":{"line":80,"col":55,"offset":2423},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.test.ts","start":{"line":12,"col":30,"offset":412},"end":{"line":12,"col":34,"offset":416},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.test.ts","start":{"line":12,"col":36,"offset":418},"end":{"line":12,"col":44,"offset":426},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts","start":{"line":89,"col":76,"offset":3098},"end":{"line":89,"col":80,"offset":3102},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts","start":{"line":218,"col":34,"offset":7053},"end":{"line":218,"col":37,"offset":7056},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts","start":{"line":218,"col":39,"offset":7058},"end":{"line":218,"col":49,"offset":7068},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts","start":{"line":38,"col":33,"offset":1015},"end":{"line":38,"col":42,"offset":1024},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts","start":{"line":49,"col":31,"offset":1370},"end":{"line":49,"col":42,"offset":1381},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts","start":{"line":49,"col":44,"offset":1383},"end":{"line":49,"col":52,"offset":1391},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts","start":{"line":38,"col":28,"offset":1438},"end":{"line":38,"col":37,"offset":1447},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts","start":{"line":40,"col":32,"offset":1517},"end":{"line":40,"col":41,"offset":1526},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts","start":{"line":58,"col":32,"offset":2062},"end":{"line":58,"col":41,"offset":2071},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.test.ts","start":{"line":8,"col":48,"offset":269},"end":{"line":8,"col":54,"offset":275},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts","start":{"line":5,"col":30,"offset":147},"end":{"line":5,"col":39,"offset":156},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts","start":{"line":7,"col":34,"offset":209},"end":{"line":7,"col":41,"offset":216},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts","start":{"line":36,"col":67,"offset":1024},"end":{"line":36,"col":75,"offset":1032},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts","start":{"line":80,"col":30,"offset":1974},"end":{"line":80,"col":39,"offset":1983},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts","start":{"line":82,"col":33,"offset":2035},"end":{"line":82,"col":40,"offset":2042},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts","start":{"line":187,"col":44,"offset":5273},"end":{"line":187,"col":61,"offset":5290},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":47,"col":30,"offset":1192},"end":{"line":47,"col":39,"offset":1201},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":49,"col":33,"offset":1253},"end":{"line":49,"col":40,"offset":1260},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":100,"col":36,"offset":2729},"end":{"line":100,"col":45,"offset":2738},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":117,"col":44,"offset":3251},"end":{"line":117,"col":53,"offset":3260},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":145,"col":35,"offset":4095},"end":{"line":145,"col":50,"offset":4110},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.test.ts","start":{"line":10,"col":53,"offset":352},"end":{"line":10,"col":59,"offset":358},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":27,"col":35,"offset":728},"end":{"line":27,"col":43,"offset":736},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":47,"col":30,"offset":1238},"end":{"line":47,"col":35,"offset":1243},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":49,"col":33,"offset":1295},"end":{"line":49,"col":40,"offset":1302},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":60,"col":25,"offset":1594},"end":{"line":60,"col":42,"offset":1611},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":95,"col":33,"offset":2573},"end":{"line":95,"col":36,"offset":2576},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":95,"col":38,"offset":2578},"end":{"line":95,"col":48,"offset":2588},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":113,"col":41,"offset":3099},"end":{"line":113,"col":50,"offset":3108},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":155,"col":32,"offset":4557},"end":{"line":155,"col":35,"offset":4560},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":155,"col":37,"offset":4562},"end":{"line":155,"col":65,"offset":4590},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":180,"col":35,"offset":5257},"end":{"line":180,"col":38,"offset":5260},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":180,"col":40,"offset":5262},"end":{"line":180,"col":44,"offset":5266},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":185,"col":34,"offset":5443},"end":{"line":185,"col":43,"offset":5452},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":188,"col":32,"offset":5551},"end":{"line":188,"col":44,"offset":5563},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":188,"col":46,"offset":5565},"end":{"line":188,"col":74,"offset":5593},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/wake.ts","start":{"line":47,"col":34,"offset":1403},"end":{"line":47,"col":51,"offset":1420},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.test.ts","start":{"line":12,"col":30,"offset":450},"end":{"line":12,"col":34,"offset":454},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.test.ts","start":{"line":12,"col":36,"offset":456},"end":{"line":12,"col":44,"offset":464},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":16,"col":25,"offset":486},"end":{"line":16,"col":34,"offset":495},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":61,"col":34,"offset":1821},"end":{"line":61,"col":37,"offset":1824},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":61,"col":39,"offset":1826},"end":{"line":61,"col":49,"offset":1836},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":158,"col":30,"offset":4687},"end":{"line":158,"col":33,"offset":4690},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":162,"col":30,"offset":4861},"end":{"line":162,"col":39,"offset":4870},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts","start":{"line":30,"col":34,"offset":954},"end":{"line":30,"col":43,"offset":963},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts","start":{"line":36,"col":34,"offset":1172},"end":{"line":36,"col":44,"offset":1182},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts","start":{"line":36,"col":46,"offset":1184},"end":{"line":36,"col":50,"offset":1188},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/search.ts","start":{"line":180,"col":40,"offset":4527},"end":{"line":180,"col":44,"offset":4531},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":36,"col":44,"offset":734},"end":{"line":36,"col":51,"offset":741},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":43,"col":20,"offset":895},"end":{"line":43,"col":43,"offset":918},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":50,"col":20,"offset":1089},"end":{"line":50,"col":43,"offset":1112},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":50,"col":45,"offset":1114},"end":{"line":50,"col":64,"offset":1133},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":162,"col":32,"offset":3837},"end":{"line":162,"col":43,"offset":3848},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":162,"col":45,"offset":3850},"end":{"line":162,"col":49,"offset":3854},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":41,"col":26,"offset":938},"end":{"line":41,"col":35,"offset":947},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":71,"col":44,"offset":1737},"end":{"line":71,"col":52,"offset":1745},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":166,"col":52,"offset":4271},"end":{"line":166,"col":64,"offset":4283},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":187,"col":21,"offset":4984},"end":{"line":187,"col":52,"offset":5015},"extra":{"message":"Detected string concatenation with a non-literal variable in a util.format / console.log function. If an attacker injects a format specifier in the string, it will forge the log message. Try to use constant values for the format string.","metadata":{"cwe":["CWE-134: Use of Externally-Controlled Format String"],"owasp":["A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"category":"security","technology":["javascript"],"subcategory":["audit"],"likelihood":"MEDIUM","impact":"LOW","confidence":"LOW","references":["https://cwe.mitre.org/data/definitions/134.html"],"license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Improper Validation"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring","shortlink":"https://sg.run/7Y5R"},"severity":"INFO","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":208,"col":36,"offset":5474},"end":{"line":208,"col":44,"offset":5482},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":208,"col":46,"offset":5484},"end":{"line":208,"col":54,"offset":5492},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":209,"col":50,"offset":5544},"end":{"line":209,"col":62,"offset":5556},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":217,"col":54,"offset":5832},"end":{"line":217,"col":62,"offset":5840},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":331,"col":36,"offset":8768},"end":{"line":331,"col":42,"offset":8774},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":368,"col":37,"offset":9863},"end":{"line":368,"col":43,"offset":9869},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":368,"col":45,"offset":9871},"end":{"line":368,"col":49,"offset":9875},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":807,"col":30,"offset":22920},"end":{"line":807,"col":39,"offset":22929},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":810,"col":34,"offset":23014},"end":{"line":810,"col":41,"offset":23021},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}}],"errors":[],"paths":{"scanned":["/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/CHANGELOG.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/README.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/SKILL.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/_meta.json","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/docs/auto-linking.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/docs/context-death.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/HOOK.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/package-lock.json","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/package.json","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/entities.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/repair-session.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/repair-session.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/wake.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/index.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/auto-linker.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/config.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/search.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/search.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-repair.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/template-engine.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/template-engine.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/time.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/types.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/checkpoint.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/daily-note.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/daily.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/decision.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/handoff.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/lesson.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/person.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/project.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/tsconfig.json"]},"time":{"rules":[],"rules_parse_time":14.36149001121521,"profiling_times":{"config_time":18.34280824661255,"core_time":28.464223861694336,"ignores_time":0.0019006729125976562,"total_time":46.84109878540039},"parsing_time":{"total_time":0.0,"per_file_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_files":[]},"scanning_time":{"total_time":19.270215272903442,"per_file_time":{"mean":0.12513126800586644,"std_dev":0.2822323039759363},"very_slow_stats":{"time_ratio":0.5083798864019303,"count_ratio":0.01948051948051948},"very_slow_files":[{"fpath":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js","ftime":1.714353084564209},{"fpath":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","ftime":2.196131944656372},{"fpath":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","ftime":5.8861048221588135}]},"matching_time":{"total_time":0.0,"per_file_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_files":[]},"tainting_time":{"total_time":0.0,"per_def_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_defs":[]},"fixpoint_timeouts":[{"error_type":"Fixpoint timeout","severity":"warn","message":"Fixpoint timeout while performing taint analysis at /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js:1:0 [rules: 4, first: javascript.lang.security.audit.dangerous-spawn-shell.dangerous-spawn-shell]","location":{"path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":1,"col":1,"offset":0},"end":{"line":1,"col":1,"offset":0}}}],"prefiltering":{"project_level_time":0.0,"file_level_time":0.0,"rules_with_project_prefilters_ratio":0.0,"rules_with_file_prefilters_ratio":0.9862007567326952,"rules_selected_ratio":0.03271756064989984,"rules_matched_ratio":0.03271756064989984},"targets":[],"total_bytes":0,"max_memory_bytes":1449516736},"engine_requested":"OSS","skipped_rules":[],"profiling_results":[]}34Process exited with code 05✓ Completed in 215536ms
mcp-scan▸1 finding165276ms
View logs
1[2026-02-13T00:36:45.392Z] $ mcp-scan --skills /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1 --json2{3 "/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt": {4 "client": "not-available",5 "path": "/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt",6 "servers": [7 {8 "name": "2026-02-10-clawhub-clawvault-1-5-1",9 "server": {10 "path": "/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1",11 "type": "skill"12 },13 "signature": {14 "metadata": {15 "meta": null,16 "protocolVersion": "built-in",17 "capabilities": {18 "experimental": null,19 "logging": null,20 "prompts": null,21 "resources": null,22 "tools": {23 "listChanged": false24 },25 "completions": null,26 "tasks": null27 },28 "serverInfo": {29 "name": "clawvault",30 "title": null,31 "version": "skills",32 "websiteUrl": null,33 "icons": null34 },35 "instructions": "Structured memory system for OpenClaw agents. Context death resilience (checkpoint/recover), structured storage, Obsidian-compatible markdown, local semantic search, and session transcript repair.",36 "prompts": {37 "listChanged": false38 },39 "resources": {40 "subscribe": null,41 "listChanged": false42 }43 },44 "prompts": [45 {46 "name": "SKILL.md",47 "title": null,48 "description": "\n\n# ClawVault \ud83d\udc18\n\nAn elephant never forgets. Structured memory for OpenClaw agents.\n\n> **Built for [OpenClaw](https://openclaw.ai)** \u2014 install via `clawhub install clawvault`\n\n## Install\n\n```bash\nnpm install -g clawvault\n```\n\n## Setup\n\n```bash\n# Initialize vault (creates folder structure + templates)\nclawvault init ~/my-vault\n\n# Or set env var to use existing vault\nexport CLAWVAULT_PATH=/path/to/memory\n\n# Optional: shell integration (aliases + CLAWVAULT_PATH)\nclawvault shell-init >> ~/.bashrc\n```\n\n## Quick Start for New Agents\n\n```bash\n# Start your session (recover + recap + summary)\nclawvault wake\n\n# Capture and checkpoint during work\nclawvault capture \"TODO: Review PR tomorrow\"\nclawvault checkpoint --working-on \"PR review\" --focus \"type guards\"\n\n# End your session with a handoff\nclawvault sleep \"PR review + type guards\" --next \"respond to CI\" --blocked \"waiting for CI\"\n\n# Health check when something feels off\nclawvault doctor\n```\n\n## Core Commands\n\n### Wake + Sleep (primary)\n\n```bash\nclawvault wake\nclawvault sleep \"what I was working on\" --next \"ship v1\" --blocked \"waiting for API key\"\n```\n\n### Store memories by type\n\n```bash\n# Types: fact, feeling, decision, lesson, commitment, preference, relationship, project\nclawvault remember decision \"Use Postgres over SQLite\" --content \"Need concurrent writes for multi-agent setup\"\nclawvault remember lesson \"Context death is survivable\" --content \"Checkpoint before heavy work\"\nclawvault remember relationship \"Justin Dukes\" --content \"Client contact at Hale Pet Door\"\n```\n\n### Quick capture to inbox\n\n```bash\nclawvault capture \"TODO: Review PR tomorrow\"\n```\n\n### Search (requires qmd installed)\n\n```bash\n# Keyword search (fast)\nclawvault search \"client contacts\"\n\n# Semantic search (slower, more accurate)\nclawvault vsearch \"what did we decide about the database\"\n```\n\n## Context Death Resilience\n\n### Wake (start of session)\n\n```bash\nclawvault wake\n```\n\n### Sleep (end of session)\n\n```bash\nclawvault sleep \"what I was working on\" --next \"finish docs\" --blocked \"waiting for review\"\n```\n\n### Checkpoint (save state frequently)\n\n```bash\nclawvault checkpoint --working-on \"PR review\" --focus \"type guards\" --blocked \"waiting for CI\"\n```\n\n### Recover (manual check)\n\n```bash\nclawvault recover --clear\n# Shows: death time, last checkpoint, recent handoff\n```\n\n### Handoff (manual session end)\n\n```bash\nclawvault handoff \\\n --working-on \"ClawVault improvements\" \\\n --blocked \"npm token\" \\\n --next \"publish to npm, create skill\" \\\n --feeling \"productive\"\n```\n\n### Recap (bootstrap new session)\n\n```bash\nclawvault recap\n# Shows: recent handoffs, active projects, pending commitments, lessons\n```\n\n## Auto-linking\n\nWiki-link entity mentions in markdown files:\n\n```bash\n# Link all files\nclawvault link --all\n\n# Link single file\nclawvault link memory/2024-01-15.md\n```\n\n## Folder Structure\n\n```\nvault/\n\u251c\u2500\u2500 .clawvault/ # Internal state\n\u2502 \u251c\u2500\u2500 last-checkpoint.json\n\u2502 \u2514\u2500\u2500 dirty-death.flag\n\u251c\u2500\u2500 decisions/ # Key choices with reasoning\n\u251c\u2500\u2500 lessons/ # Insights and patterns\n\u251c\u2500\u2500 people/ # One file per person\n\u251c\u2500\u2500 projects/ # Active work tracking\n\u251c\u2500\u2500 handoffs/ # Session continuity\n\u251c\u2500\u2500 inbox/ # Quick captures\n\u2514\u2500\u2500 templates/ # Document templates\n```\n\n## Best Practices\n\n1. **Wake at session start** \u2014 `clawvault wake` restores context\n2. **Checkpoint every 10-15 min** during heavy work\n3. **Sleep before session end** \u2014 `clawvault sleep` captures next steps\n4. **Use types** \u2014 knowing WHAT you're storing helps WHERE to put it\n5. **Wiki-link liberally** \u2014 `[[person-name]]` builds your knowledge graph\n\n## Checklist for AGENTS.md\n\n```markdown\n## Memory Checklist\n- [ ] Run `clawvault wake` at session start\n- [ ] Checkpoint during heavy work\n- [ ] Capture key decisions/lessons with `clawvault remember`\n- [ ] Use wiki-links like `[[person-name]]`\n- [ ] End with `clawvault sleep \"...\" --next \"...\" --blocked \"...\"`\n- [ ] Run `clawvault doctor` when something feels off\n```\n\n## Session Transcript Repair (v1.5.0+)\n\nWhen the Anthropic API rejects with \"unexpected tool_use_id found in tool_result blocks\", use:\n\n```bash\n# See what's wrong (dry-run)\nclawvault repair-session --dry-run\n\n# Fix it\nclawvault repair-session\n\n# Repair a specific session\nclawvault repair-session --session <id> --agent <agent-id>\n\n# List available sessions\nclawvault repair-session --list\n```\n\n**What it fixes:**\n- Orphaned `tool_result` blocks referencing non-existent `tool_use` IDs\n- Aborted tool calls with partial JSON\n- Broken parent chain references\n\nBackups are created automatically (use `--no-backup` to skip).\n\n## Troubleshooting\n\n- **qmd not installed** \u2014 run `bun install -g github:tobi/qmd` or `npm install -g qmd`\n- **No ClawVault found** \u2014 run `clawvault init` or set `CLAWVAULT_PATH`\n- **CLAWVAULT_PATH missing** \u2014 run `clawvault shell-init` and add to shell rc\n- **Too many orphan links** \u2014 run `clawvault link --orphans`\n- **Inbox backlog warning** \u2014 process or archive inbox items\n- **\"unexpected tool_use_id\" error** \u2014 run `clawvault repair-session`\n\n## Integration with qmd\n\nClawVault uses [qmd](https://github.com/tobi/qmd) for search:\n\n```bash\n# Install qmd\nbun install -g github:tobi/qmd\n\n# Add vault as collection\nqmd collection add /path/to/vault --name my-memory --mask \"**/*.md\"\n\n# Update index\nqmd update && qmd embed\n```\n\n## Environment Variables\n\n- `CLAWVAULT_PATH` \u2014 Default vault path (skips auto-discovery)\n\n## Links\n\n- npm: https://www.npmjs.com/package/clawvault\n- GitHub: https://github.com/Versatly/clawvault\n- Issues: https://github.com/Versatly/clawvault/issues\n",49 "arguments": [],50 "icons": null,51 "meta": null52 },53 {54 "name": "templates/decision.md",55 "title": null,56 "description": "---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\nstatus: decided\n---\n\n# Decision: {{title}}\n\n## Context\n- \n\n## Decision\n- \n\n## Consequences\n- \n",57 "arguments": null,58 "icons": null,59 "meta": null60 },61 {62 "name": "templates/handoff.md",63 "title": null,64 "description": "---\ntitle: \"Handoff {{datetime}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# Session Handoff\n\n## Working On\n- \n\n## Blocked\n- \n\n## Next\n- [ ]\n\n## Notes\n- \n",65 "arguments": null,66 "icons": null,67 "meta": null68 },69 {70 "name": "templates/person.md",71 "title": null,72 "description": "---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\nrelationship: contact\n---\n\n# {{title}}\n\n## Context\n- \n\n## Details\n- Contact:\n- Role:\n- Timezone:\n\n## History\n- {{date}}: \n",73 "arguments": null,74 "icons": null,75 "meta": null76 },77 {78 "name": "templates/daily.md",79 "title": null,80 "description": "---\ntitle: \"{{date}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# {{date}}\n\n## Focus\n- \n\n## Wins\n- \n\n## Notes\n- \n\n## Next\n- [ ]\n",81 "arguments": null,82 "icons": null,83 "meta": null84 },85 {86 "name": "templates/lesson.md",87 "title": null,88 "description": "---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# Lesson: {{title}}\n\n## Insight\n- \n\n## Evidence\n- \n\n## Application\n- \n",89 "arguments": null,90 "icons": null,91 "meta": null92 },93 {94 "name": "templates/daily-note.md",95 "title": null,96 "description": "---\ntitle: \"{{date}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# {{date}}\n\n## Focus\n- \n\n## Wins\n- \n\n## Notes\n- \n\n## Next\n- [ ]\n",97 "arguments": null,98 "icons": null,99 "meta": null100 },101 {102 "name": "templates/checkpoint.md",103 "title": null,104 "description": "---\ntitle: \"Checkpoint {{datetime}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# Checkpoint\n\n## Working On\n- \n\n## Focus\n- \n\n## Blocked\n- \n\n## Notes\n- \n",105 "arguments": null,106 "icons": null,107 "meta": null108 },109 {110 "name": "templates/project.md",111 "title": null,112 "description": "---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\nstatus: active\n---\n\n# {{title}}\n\n## Objective\n- \n\n## Status\n- [ ] Planning\n- [ ] In progress\n- [ ] Blocked\n- [ ] Done\n\n## Next\n- [ ]\n\n## Notes\n- \n",113 "arguments": null,114 "icons": null,115 "meta": null116 },117 {118 "name": "README.md",119 "title": null,120 "description": "# ClawVault \ud83d\udc18\n\n**An elephant never forgets.**\n\nStructured memory system for AI agents. Store, search, and link memories across sessions.\n\n> **Built for [OpenClaw](https://openclaw.ai)** \u2014 the AI agent framework. Works standalone too.\n\n## Install for OpenClaw Agents\n\n```bash\n# Install the skill (recommended for OpenClaw agents)\nclawhub install clawvault\n\n# Or install the CLI globally\nnpm install -g clawvault\n```\n\n## Requirements\n\n- **Node.js 18+**\n- **[qmd](https://github.com/Versatly/qmd)** \u2014 Local semantic search (required)\n\n```bash\n# Install qmd first\nbun install -g qmd # or: npm install -g qmd\n\n# Then install clawvault\nnpm install -g clawvault\n```\n\n## Why ClawVault?\n\nAI agents forget things. Context windows overflow, sessions end, important details get lost. ClawVault fixes that:\n\n- **Structured storage** \u2014 Organized categories, not random notes\n- **Local search** \u2014 qmd provides BM25 + semantic search with local embeddings (no API quotas)\n- **Wiki-links** \u2014 `[[connections]]` visible in Obsidian's graph view\n- **Session continuity** \u2014 Handoff/recap system for context death\n- **Token efficient** \u2014 Search instead of loading entire memory files\n\n## Quick Start\n\n```bash\n# Initialize vault with qmd collection\nclawvault init ~/memory --qmd-collection my-memory\n\n# Store memories\nclawvault remember decision \"Use qmd\" --content \"Local embeddings, no API limits\"\nclawvault remember lesson \"Context death is survivable\" --content \"Write it down\"\nclawvault capture \"Quick note to process later\"\n\n# Search (uses qmd)\nclawvault search \"decision\" # BM25 keyword search\nclawvault vsearch \"what did I decide\" # Semantic search\n\n# Session management\nclawvault wake\nclawvault sleep \"build wake/sleep commands\" --next \"run doctor\"\nclawvault handoff --working-on \"task1\" --next \"task2\" # Manual handoff (advanced)\nclawvault recap # Manual recap (advanced)\n```\n\n**Tip:** Set `CLAWVAULT_PATH` to skip directory walk (or use `shell-init`):\n```bash\necho 'export CLAWVAULT_PATH=\"$HOME/memory\"' >> ~/.bashrc\neval \"$(clawvault shell-init)\"\n```\n\n## Search: qmd vs memory_search\n\n**Use `qmd` (or `clawvault search`) \u2014 not `memory_search`**\n\n| Tool | Backend | Speed | API Limits |\n|------|---------|-------|------------|\n| `qmd search` / `clawvault search` | Local BM25 | Instant | None |\n| `qmd vsearch` / `clawvault vsearch` | Local embeddings | Fast | None |\n| `memory_search` | Gemini API | Variable | **Yes, hits quotas** |\n\n```bash\n# \u2705 Use this\nqmd search \"query\" -c my-memory\nclawvault search \"query\"\n\n# \u274c Avoid (API quotas)\nmemory_search\n```\n\n## Vault Structure\n\n```\nmy-memory/\n\u251c\u2500\u2500 .clawvault.json # Config (includes qmd collection name)\n\u251c\u2500\u2500 decisions/ # Choices with reasoning\n\u251c\u2500\u2500 lessons/ # Things learned\n\u251c\u2500\u2500 people/ # One file per person\n\u251c\u2500\u2500 projects/ # Active work\n\u251c\u2500\u2500 commitments/ # Promises and deadlines\n\u251c\u2500\u2500 inbox/ # Quick capture (process later)\n\u2514\u2500\u2500 handoffs/ # Session continuity\n```\n\n## Commands\n\n### Store Memories\n\n```bash\n# With type classification (recommended)\nclawvault remember <type> <title> --content \"...\"\n# Types: decision, lesson, fact, commitment, project, person\n\n# Quick capture\nclawvault capture \"Note to self\"\n\n# Manual store\nclawvault store -c decisions -t \"Title\" --content \"...\"\n```\n\n**Note:** All write commands auto-update the qmd index. Use `--no-index` to skip.\n\n### Search\n\n```bash\nclawvault search \"query\" # BM25 keyword\nclawvault search \"query\" -c people # Filter by category\nclawvault vsearch \"query\" # Semantic (local embeddings)\n```\n\n### Browse\n\n```bash\nclawvault list # All documents\nclawvault list decisions # By category\nclawvault get decisions/title # Specific document\nclawvault stats # Vault overview\n```\n\n### Session Continuity\n\n```bash\n# Start a session (recover + recap + summary)\nclawvault wake\n\n# End a session with a handoff\nclawvault sleep \"building CRM, fixing webhook\" \\\n --blocked \"waiting for API key\" \\\n --next \"deploy to production\" \\\n --decisions \"chose Supabase over Firebase\" \\\n --feeling \"focused\"\n\n# Manual tools (advanced)\nclawvault handoff --working-on \"task1\" --next \"task2\"\nclawvault recap --brief # Token-efficient recap\n\n# Health check\nclawvault doctor\n```\n\n## Agent Setup (AGENTS.md)\n\nAdd this to your `AGENTS.md` to ensure proper memory habits:\n\n```markdown\n## Memory\n\n**Write everything down. Memory doesn't survive session restarts.**\n\n### Search (use qmd, not memory_search)\n\\`\\`\\`bash\nqmd search \"query\" -c your-memory # Fast keyword\nqmd vsearch \"query\" -c your-memory # Semantic\n\\`\\`\\`\n\n### Store\n\\`\\`\\`bash\nclawvault remember decision \"Title\" --content \"...\"\nclawvault remember lesson \"Title\" --content \"...\"\n\\`\\`\\`\n\n### Session Start\n\\`\\`\\`bash\nclawvault wake\n\\`\\`\\`\n\n### Session End\n\\`\\`\\`bash\nclawvault sleep \"...\" --next \"...\"\n\\`\\`\\`\n\n### Checkpoint (during heavy work)\n\\`\\`\\`bash\nclawvault checkpoint --working-on \"...\" --focus \"...\" --blocked \"...\"\n\\`\\`\\`\n\n### Why qmd over memory_search?\n- Local embeddings \u2014 no API quotas\n- Always works \u2014 no external dependencies\n- Fast \u2014 instant BM25, quick semantic\n```\n\n## Templates\n\nClawVault includes templates for common memory types:\n\n- `decision.md` \u2014 Choices with context and reasoning\n- `lesson.md` \u2014 Things learned\n- `person.md` \u2014 People you work with\n- `project.md` \u2014 Active work\n- `handoff.md` \u2014 Session state before context death\n- `daily.md` \u2014 Daily notes\n\nUse with: `clawvault store -c category -t \"Title\" -f decision`\n\n## Library Usage\n\n```typescript\nimport { ClawVault, createVault, findVault } from 'clawvault';\n\nconst vault = await createVault('./memory', { qmdCollection: 'my-memory' });\n\nawait vault.store({\n category: 'decisions',\n title: 'Use ClawVault',\n content: 'Decided to use ClawVault for memory.',\n});\n\nconst results = await vault.find('memory', { limit: 5 });\n```\n\n## License\n\nMIT\n\n---\n\n*\"An elephant never forgets.\" \u2014 Now neither do you.* \ud83d\udc18\n",121 "arguments": null,122 "icons": null,123 "meta": null124 },125 {126 "name": "CHANGELOG.md",127 "title": null,128 "description": "# Changelog\n\n## [1.5.1] - 2026-02-06\n\n### Security\n- **Fixed shell injection vulnerability** in hooks/clawvault/handler.js\n - Changed from `execSync` (with shell) to `execFileSync` (no shell)\n - All arguments passed as array, never interpolated into shell string\n - Vault path validation: must be absolute, exist, and contain .clawvault.json\n\n- **Fixed prompt injection vulnerability**\n - Checkpoint recovery data now sanitized before injection\n - Control characters stripped, markdown escaped, length limited\n - Session keys and command sources sanitized with strict allowlist\n\n- **Removed direct GitHub dependency** for qmd\n - qmd moved to optional peer dependency\n - Users install separately: `npm install -g github:tobi/qmd`\n - ClawVault gracefully handles missing qmd\n\n### Changed\n- Hook now validates vault paths before use\n- Error messages in hooks are now generic (no sensitive data leaked)\n\n---\n\n## [1.5.0] - 2026-02-06\n\n### Added\n- **`clawvault repair-session`** - Repair corrupted OpenClaw session transcripts\n - Detects orphaned `tool_result` blocks that reference non-existent `tool_use` IDs\n - Identifies aborted tool calls with partial JSON\n - Automatically relinks parent chain after removals\n - Creates backup before repair (configurable with `--no-backup`)\n - Dry-run mode with `--dry-run` to preview repairs\n - List sessions with `--list` flag\n - JSON output with `--json` for scripting\n \n **Problem solved:** When the Anthropic API rejects with \"unexpected tool_use_id found in tool_result blocks\", this command fixes the transcript so the session can continue without losing context.\n \n ```bash\n # Analyze without changing\n clawvault repair-session --dry-run\n \n # Repair current main session\n clawvault repair-session\n \n # Repair specific session\n clawvault repair-session --session <id> --agent <agent-id>\n ```\n\n- **Session utilities** (`src/lib/session-utils.ts`)\n - `listAgents()` - Find all agents in ~/.openclaw/agents/\n - `findMainSession()` - Get current session for an agent\n - `findSessionById()` - Look up specific session\n - `getSessionFilePath()`, `backupSession()` - File helpers\n\n### Tests\n- Added 13 tests for session repair functionality\n - Transcript parsing\n - Tool use extraction from assistant messages\n - Corruption detection (aborted + orphaned)\n - Parent chain relinking\n - Dry-run mode\n - Backup creation\n\n---\n\n## [1.4.2] - 2026-02-06\n\n### Added\n- **OpenClaw Hook Integration** - Automatic context death resilience\n - `gateway:startup` event: Detects if previous session died, injects alert into first agent turn\n - `command:new` event: Auto-checkpoints before session reset\n - Install: `openclaw hooks install clawvault && openclaw hooks enable clawvault`\n - Hook ships with npm package via `openclaw.hooks` field in package.json\n\n- **`clawvault wake`** - All-in-one session start command\n - Combines: `recover --clear` + `recap` + summary\n - Shows context death status, recent handoffs, what you were working on\n - Perfect for session startup ritual\n\n- **`clawvault sleep <summary>`** - All-in-one session end command\n - Creates handoff with: --next, --blocked, --decisions, --questions, --feeling\n - Clears death flag\n - Optional git commit prompt (--no-git to skip)\n - Captures rich context before ending session\n\n### Fixed\n- Fixed readline import in sleep command (was using `readline/promises` which bundlers couldn't resolve)\n\n### Changed\n- Documentation updated for hook-first approach\n- AGENTS.md simplified - hook handles basics, manual commands for rich context\n- SKILL.md updated with OpenClaw Integration section\n\n---\n\n## [1.4.1] - 2026-02-05\n\n### Added\n- `clawvault doctor` - Vault health diagnostics\n- `clawvault shell-init` - Shell integration setup\n\n---\n\n## [1.4.0] - 2026-02-04\n\n### Added\n- **qmd integration** - Semantic search via local embeddings\n- `clawvault setup` - Auto-discovers OpenClaw memory folder\n- `clawvault status` - Vault health, checkpoint age, qmd index\n- `clawvault template` - List/create/add with 7 built-in templates\n- `clawvault link --backlinks` - See what links to a file\n- `clawvault link --orphans` - Find broken wiki-links\n\n### Changed\n- qmd is now required for semantic search functionality\n\n---\n\n## [1.3.x] - Earlier\n\n- Initial release with core functionality\n- Checkpoint/recover for context death resilience\n- Handoff/recap for session continuity\n- Wiki-linking and entity management\n- Structured memory categories\n",129 "arguments": null,130 "icons": null,131 "meta": null132 },133 {134 "name": "docs/context-death.md",135 "title": null,136 "description": "# Context Death Resilience\n\n**Problem:** When an agent hits context overflow, it dies mid-thought with no chance to save state. The next session starts fresh with no memory of what was happening.\n\n**Solution:** Multi-layered defense against context death.\n\n## Architecture\n\n### Layer 1: Periodic Checkpoints (HEARTBEAT)\n- Add `clawvault checkpoint` to HEARTBEAT.md\n- Quick, lightweight save every few heartbeats\n- Captures: working-on, recent decisions, current focus\n\n### Layer 2: Pre-Compaction Flush\n- OpenClaw already has `compaction.memoryFlush`\n- Hook into this to also run `clawvault handoff --pre-compact`\n- Gives agent one last chance to save before context shrinks\n\n### Layer 3: Emergency Handoff (Gateway Hook)\n- New hook: `agent:context_overflow`\n- Runs `clawvault emergency-save` from last known state\n- Parses session transcript to extract what was happening\n- Works even when agent can't respond\n\n### Layer 4: Auto-Recap on Bootstrap\n- Check for \"dirty death\" flag on startup\n- If found, inject recap + context death notice\n- Agent knows it died and can resume\n\n## Commands\n\n### `clawvault checkpoint`\nQuick state save (runs in <1s):\n```bash\nclawvault checkpoint --working-on \"docs study\" --focus \"config parsing\"\n```\n\n### `clawvault emergency-save`\nCalled by gateway when context overflows:\n```bash\nclawvault emergency-save --session-file ~/.openclaw/sessions/xxx.jsonl\n```\n- Parses last N messages from transcript\n- Extracts what agent was doing\n- Creates emergency handoff\n\n### `clawvault recover`\nCheck for dirty death and get recovery info:\n```bash\nclawvault recover\n# Returns: { died: true, recap: \"...\", lastHandoff: \"...\" }\n```\n\n## State Files\n\n```\nmemory/\n\u251c\u2500\u2500 .clawvault/\n\u2502 \u251c\u2500\u2500 session-state.json # Current session tracker\n\u2502 \u251c\u2500\u2500 last-checkpoint.json # Quick checkpoint data\n\u2502 \u2514\u2500\u2500 dirty-death.flag # Set on crash, cleared on clean exit\n```\n\n## Integration Points\n\n### AGENTS.md Bootstrap\n```markdown\n## Every Session\n1. Run `clawvault recover` - check if last session died\n2. If died: load emergency handoff, acknowledge context death\n3. Run `clawvault recap` for normal continuity\n```\n\n### HEARTBEAT.md\n```markdown\n## Checkpoint (every 4-6 heartbeats)\n- Run `clawvault checkpoint` with current focus\n```\n\n### OpenClaw Hook (context-death-handler)\n```typescript\nconst handler: HookHandler = async (event) => {\n if (event.type === 'agent' && event.action === 'context_overflow') {\n await execSync('clawvault emergency-save --session-file ' + event.context.sessionFile);\n }\n};\n```\n\n## Implementation Priority\n\n1. \u2705 `clawvault handoff` - Already exists\n2. \ud83d\udd32 `clawvault checkpoint` - Quick version of handoff\n3. \ud83d\udd32 `clawvault emergency-save` - Parse transcript on crash\n4. \ud83d\udd32 `clawvault recover` - Detect dirty death\n5. \ud83d\udd32 OpenClaw hook - Trigger emergency save\n6. \ud83d\udd32 Bootstrap integration - Auto-inject on restart\n\n## Open Questions\n\n- Does OpenClaw emit an event on context overflow? Need to check.\n- Can we detect \"about to overflow\" before it happens?\n- Should checkpoint be a cron job or HEARTBEAT task?\n",137 "arguments": null,138 "icons": null,139 "meta": null140 },141 {142 "name": "docs/auto-linking.md",143 "title": null,144 "description": "# ClawVault Auto-Linking Spec\n\n## Problem\nAgents forget to use `[[wiki-links]]` when writing memories, making the Obsidian graph sparse and connections invisible.\n\n## Solution: Automatic Entity Linking\n\n### 1. Entity Registry (`memory/.entities.json`)\n```json\n{\n \"people\": {\n \"pedro\": {\n \"path\": \"people/pedro\",\n \"aliases\": [\"Pedro\", \"Chief\", \"my human\", \"the boss\"]\n },\n \"justin-dukes\": {\n \"path\": \"people/justin-dukes\", \n \"aliases\": [\"Justin\", \"Justin Dukes\", \"Hale contact\"]\n }\n },\n \"projects\": {\n \"site-machine\": {\n \"path\": \"projects/site-machine\",\n \"aliases\": [\"Site Machine\", \"the business\", \"income project\"]\n }\n },\n \"agents\": {\n \"forge\": {\n \"path\": \"agents/forge\",\n \"aliases\": [\"Forge\", \"business agent\", \"the sales agent\"]\n }\n }\n}\n```\n\n### 2. Auto-Link on Write\nWhen `clawvault remember` saves a file:\n1. Load entity registry\n2. Scan content for alias matches (case-insensitive, word-boundary)\n3. Replace first occurrence of each entity with `[[path|alias]]`\n4. Skip if already inside a link or code block\n\n### 3. CLI Commands\n```bash\n# Register new entity\nclawvault entity add pedro --path people/pedro --aliases \"Pedro,Chief,my human\"\n\n# Link a single file\nclawvault link memory/2026-01-31.md\n\n# Link all files in vault\nclawvault link --all\n\n# Show unlinked entity mentions\nclawvault link --dry-run\n```\n\n### 4. Integration Points\n- `clawvault remember` \u2014 auto-link before write\n- `clawvault handoff` \u2014 auto-link the handoff content\n- New `clawvault link` command for batch processing\n\n### 5. Edge Cases\n- Don't link inside code blocks or frontmatter\n- Don't double-link (check if text is already `[[linked]]`)\n- Prefer longer aliases first (\"Justin Dukes\" before \"Justin\")\n- Only link first occurrence per entity per file (avoid spam)\n\n## Implementation Priority\n1. Entity registry JSON structure\n2. `clawvault entity add/list/remove` commands\n3. Link scanner utility\n4. Integration with `remember` command\n5. Batch `link --all` command\n",145 "arguments": null,146 "icons": null,147 "meta": null148 },149 {150 "name": "hooks/clawvault/HOOK.md",151 "title": null,152 "description": "---\nname: clawvault\ndescription: \"Context death resilience - auto-checkpoint and recovery detection\"\nmetadata:\n openclaw:\n emoji: \"\ud83d\udc18\"\n events: [\"gateway:startup\", \"command:new\"]\n requires:\n bins: [\"clawvault\"]\n---\n\n# ClawVault Hook\n\nIntegrates ClawVault's context death resilience into OpenClaw:\n\n- **On gateway startup**: Checks for context death, alerts agent\n- **On /new command**: Auto-checkpoints before session reset\n\n## Installation\n\n```bash\nnpm install -g clawvault\nopenclaw hooks install clawvault\nopenclaw hooks enable clawvault\n```\n\n## Requirements\n\n- ClawVault CLI installed globally\n- Vault initialized (`clawvault setup` or `CLAWVAULT_PATH` set)\n\n## What It Does\n\n### Gateway Startup\n\n1. Runs `clawvault recover --clear`\n2. If context death detected, injects warning into first agent turn\n3. Clears dirty death flag for clean session start\n\n### Command: /new\n\n1. Creates automatic checkpoint with session info\n2. Captures state even if agent forgot to handoff\n3. Ensures continuity across session resets\n\n## No Configuration Needed\n\nJust enable the hook. It auto-detects vault path via:\n\n1. `CLAWVAULT_PATH` environment variable\n2. Walking up from cwd to find `.clawvault.json`\n",153 "arguments": null,154 "icons": null,155 "meta": null156 }157 ],158 "resources": [159 {160 "name": "package.json",161 "title": null,162 "uri": "skill://package.json",163 "description": "{\n \"name\": \"clawvault\",\n \"version\": \"1.5.1\",\n \"description\": \"\ud83d\udc18 An elephant never forgets. Structured memory for OpenClaw agents. Context death resilience, Obsidian-compatible markdown, local semantic search.\",\n \"type\": \"module\",\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"bin\": {\n \"clawvault\": \"./bin/clawvault.js\"\n },\n \"files\": [\n \"dist\",\n \"bin\",\n \"templates\",\n \"hooks\"\n ],\n \"openclaw\": {\n \"hooks\": [\n \"./hooks/clawvault\"\n ]\n },\n \"scripts\": {\n \"build\": \"tsup src/index.ts src/commands/entities.ts src/commands/link.ts src/commands/checkpoint.ts src/commands/recover.ts src/commands/status.ts src/commands/template.ts src/commands/setup.ts src/commands/wake.ts src/commands/sleep.ts src/commands/doctor.ts src/commands/shell-init.ts src/commands/repair-session.ts src/lib/entity-index.ts src/lib/auto-linker.ts src/lib/config.ts src/lib/template-engine.ts src/lib/session-utils.ts src/lib/session-repair.ts --format esm --dts --clean\",\n \"dev\": \"tsup src/index.ts src/commands/*.ts src/lib/*.ts --format esm --dts --watch\",\n \"lint\": \"eslint src\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"keywords\": [\n \"openclaw\",\n \"ai\",\n \"agent\",\n \"memory\",\n \"vault\",\n \"obsidian\",\n \"markdown\",\n \"semantic-search\",\n \"context-death\",\n \"llm\"\n ],\n \"author\": \"Versatly\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Versatly/clawvault.git\"\n },\n \"homepage\": \"https://github.com/Versatly/clawvault#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/Versatly/clawvault/issues\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"dependencies\": {\n \"commander\": \"^12.0.0\",\n \"chalk\": \"^5.3.0\",\n \"glob\": \"^10.3.10\",\n \"gray-matter\": \"^4.0.3\",\n \"natural\": \"^6.10.4\"\n },\n \"optionalDependencies\": {},\n \"peerDependencies\": {\n \"qmd\": \"*\"\n },\n \"peerDependenciesMeta\": {\n \"qmd\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.11.0\",\n \"tsup\": \"^8.0.1\",\n \"typescript\": \"^5.3.3\",\n \"vitest\": \"^1.2.0\"\n }\n}\n",164 "mimeType": null,165 "size": null,166 "icons": null,167 "annotations": null,168 "meta": null169 },170 {171 "name": "_meta.json",172 "title": null,173 "uri": "skill://_meta.json",174 "description": "{\n \"owner\": \"pin-alt\",\n \"slug\": \"2026-02-10-clawhub-clawvault-1-5-1\",\n \"displayName\": \"2026 02 10 Clawhub Clawvault 1.5.1\",\n \"latest\": {\n \"version\": \"1.0.0\",\n \"publishedAt\": 1770876286850,\n \"commit\": \"https://github.com/openclaw/skills/commit/17c27532596fd1a4dbb81c5b1fcd063f878c827e\"\n },\n \"history\": []\n}\n",175 "mimeType": null,176 "size": null,177 "icons": null,178 "annotations": null,179 "meta": null180 },181 {182 "name": "tsconfig.json",183 "title": null,184 "uri": "skill://tsconfig.json",185 "description": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"NodeNext\",\n \"moduleResolution\": \"NodeNext\",\n \"lib\": [\"ES2022\"],\n \"declaration\": true,\n \"declarationMap\": true,\n \"sourceMap\": true,\n \"outDir\": \"./dist\",\n \"rootDir\": \"./src\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"forceConsistentCasingInFileNames\": true,\n \"resolveJsonModule\": true\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\", \"dist\"]\n}\n",186 "mimeType": null,187 "size": null,188 "icons": null,189 "annotations": null,190 "meta": null191 },192 {193 "name": "package-lock.json",194 "title": null,195 "uri": "skill://package-lock.json",196 "description": "{\n \"name\": \"clawvault\",\n \"version\": \"1.4.2\",\n \"lockfileVersion\": 3,\n \"requires\": true,\n \"packages\": {\n \"\": {\n \"name\": \"clawvault\",\n \"version\": \"1.4.2\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"chalk\": \"^5.3.0\",\n \"commander\": \"^12.0.0\",\n \"glob\": \"^10.3.10\",\n \"gray-matter\": \"^4.0.3\",\n \"natural\": \"^6.10.4\",\n \"qmd\": \"github:tobi/qmd\"\n },\n \"bin\": {\n \"clawvault\": \"bin/clawvault.js\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.11.0\",\n \"tsup\": \"^8.0.1\",\n \"typescript\": \"^5.3.3\",\n \"vitest\": \"^1.2.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/aix-ppc64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz\",\n \"integrity\": \"sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"aix\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/android-arm\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz\",\n \"integrity\": \"sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/android-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/android-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/darwin-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/darwin-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/freebsd-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/freebsd-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-arm\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz\",\n \"integrity\": \"sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-ia32\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz\",\n \"integrity\": \"sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-loong64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz\",\n \"integrity\": \"sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==\",\n \"cpu\": [\n \"loong64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-mips64el\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz\",\n \"integrity\": \"sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==\",\n \"cpu\": [\n \"mips64el\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-ppc64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz\",\n \"integrity\": \"sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-riscv64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz\",\n \"integrity\": \"sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==\",\n \"cpu\": [\n \"riscv64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-s390x\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz\",\n \"integrity\": \"sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==\",\n \"cpu\": [\n \"s390x\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/netbsd-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"netbsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/netbsd-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"netbsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/openbsd-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openbsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/openbsd-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openbsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/openharmony-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openharmony\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/sunos-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"sunos\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/win32-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/win32-ia32\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz\",\n \"integrity\": \"sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/win32-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@hono/node-server\": {\n \"version\": \"1.19.9\",\n \"resolved\": \"https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz\",\n \"integrity\": \"sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18.14.1\"\n },\n \"peerDependencies\": {\n \"hono\": \"^4\"\n }\n },\n \"node_modules/@huggingface/jinja\": {\n \"version\": \"0.5.5\",\n \"resolved\": \"https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.5.tgz\",\n \"integrity\": \"sha512-xRlzazC+QZwr6z4ixEqYHo9fgwhTZ3xNSdljlKfUFGZSdlvt166DljRELFUfFytlYOYvo3vTisA/AFOuOAzFQQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@isaacs/cliui\": {\n \"version\": \"8.0.2\",\n \"resolved\": \"https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz\",\n \"integrity\": \"sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"string-width\": \"^5.1.2\",\n \"string-width-cjs\": \"npm:string-width@^4.2.0\",\n \"strip-ansi\": \"^7.0.1\",\n \"strip-ansi-cjs\": \"npm:strip-ansi@^6.0.1\",\n \"wrap-ansi\": \"^8.1.0\",\n \"wrap-ansi-cjs\": \"npm:wrap-ansi@^7.0.0\"\n },\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/@jest/schemas\": {\n \"version\": \"29.6.3\",\n \"resolved\": \"https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz\",\n \"integrity\": \"sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@sinclair/typebox\": \"^0.27.8\"\n },\n \"engines\": {\n \"node\": \"^14.15.0 || ^16.10.0 || >=18.0.0\"\n }\n },\n \"node_modules/@jridgewell/gen-mapping\": {\n \"version\": \"0.3.13\",\n \"resolved\": \"https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz\",\n \"integrity\": \"sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jridgewell/sourcemap-codec\": \"^1.5.0\",\n \"@jridgewell/trace-mapping\": \"^0.3.24\"\n }\n },\n \"node_modules/@jridgewell/resolve-uri\": {\n \"version\": \"3.1.2\",\n \"resolved\": \"https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz\",\n \"integrity\": \"sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=6.0.0\"\n }\n },\n \"node_modules/@jridgewell/sourcemap-codec\": {\n \"version\": \"1.5.5\",\n \"resolved\": \"https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz\",\n \"integrity\": \"sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@jridgewell/trace-mapping\": {\n \"version\": \"0.3.31\",\n \"resolved\": \"https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz\",\n \"integrity\": \"sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jridgewell/resolve-uri\": \"^3.1.0\",\n \"@jridgewell/sourcemap-codec\": \"^1.4.14\"\n }\n },\n \"node_modules/@kwsites/file-exists\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz\",\n \"integrity\": \"sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"debug\": \"^4.1.1\"\n }\n },\n \"node_modules/@kwsites/promise-deferred\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz\",\n \"integrity\": \"sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/@modelcontextprotocol/sdk\": {\n \"version\": \"1.25.3\",\n \"resolved\": \"https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.3.tgz\",\n \"integrity\": \"sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@hono/node-server\": \"^1.19.9\",\n \"ajv\": \"^8.17.1\",\n \"ajv-formats\": \"^3.0.1\",\n \"content-type\": \"^1.0.5\",\n \"cors\": \"^2.8.5\",\n \"cross-spawn\": \"^7.0.5\",\n \"eventsource\": \"^3.0.2\",\n \"eventsource-parser\": \"^3.0.0\",\n \"express\": \"^5.0.1\",\n \"express-rate-limit\": \"^7.5.0\",\n \"jose\": \"^6.1.1\",\n \"json-schema-typed\": \"^8.0.2\",\n \"pkce-challenge\": \"^5.0.0\",\n \"raw-body\": \"^3.0.0\",\n \"zod\": \"^3.25 || ^4.0\",\n \"zod-to-json-schema\": \"^3.25.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"peerDependencies\": {\n \"@cfworker/json-schema\": \"^4.1.1\",\n \"zod\": \"^3.25 || ^4.0\"\n },\n \"peerDependenciesMeta\": {\n \"@cfworker/json-schema\": {\n \"optional\": true\n },\n \"zod\": {\n \"optional\": false\n }\n }\n },\n \"node_modules/@mongodb-js/saslprep\": {\n \"version\": \"1.4.5\",\n \"resolved\": \"https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.5.tgz\",\n \"integrity\": \"sha512-k64Lbyb7ycCSXHSLzxVdb2xsKGPMvYZfCICXvDsI8Z65CeWQzTEKS4YmGbnqw+U9RBvLPTsB6UCmwkgsDTGWIw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"sparse-bitfield\": \"^3.0.3\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-arm64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-arm64/-/linux-arm64-3.15.1.tgz\",\n \"integrity\": \"sha512-g7JC/WwDyyBSmkIjSvRF2XLW+YA0z2ZVBSAKSv106mIPO4CzC078woTuTaPsykWgIaKcQRyXuW5v5XQMcT1OOA==\",\n \"cpu\": [\n \"arm64\",\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-armv7l\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-armv7l/-/linux-armv7l-3.15.1.tgz\",\n \"integrity\": \"sha512-MSxR3A0vFSVWbmVSkNqNXQnI45L2Vg7/PRgJukcjChk7YzRxs9L+oQMeycVW3BsQ03mIZ0iORsZ9MNIBEbdS3g==\",\n \"cpu\": [\n \"arm\",\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-x64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-x64/-/linux-x64-3.15.1.tgz\",\n \"integrity\": \"sha512-w4SdxJaA9eJLVYWX+Jv48hTP4oO79BJQIFURMi7hXIFXbxyyOov/r6sVaQ1WiL83nVza37U5Qg4L9Gb/KRdNWQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-x64-cuda\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-x64-cuda/-/linux-x64-cuda-3.15.1.tgz\",\n \"integrity\": \"sha512-kngwoq1KdrqSr/b6+tn5jbtGHI0tZnW5wofKssZy+Il2ge3eN9FowKbXG4FH452g6qSSVoDccAoTvYOxyLyX+w==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-x64-cuda-ext\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-x64-cuda-ext/-/linux-x64-cuda-ext-3.15.1.tgz\",\n \"integrity\": \"sha512-toepvLcXjgaQE/QGIThHBD58jbHGBWT1jhblJkCjYBRHfVOO+6n/PmVsJt+yMfu5Z93A2gF8YOvVyZXNXmGo5g==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-x64-vulkan\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-x64-vulkan/-/linux-x64-vulkan-3.15.1.tgz\",\n \"integrity\": \"sha512-CMsyQkGKpHKeOH9+ZPxo0hO0usg8jabq5/aM3JwdX9CiuXhXUa3nu3NH4RObiNi596Zwn/zWzlps0HRwcpL8rw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/mac-arm64-metal\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/mac-arm64-metal/-/mac-arm64-metal-3.15.1.tgz\",\n \"integrity\": \"sha512-ePTweqohcy6Gjs1agXWy4FxAw5W4Avr7NeqqiFWJ5ngZ1U3ZXdruUHB8L/vDxyn3FzKvstrFyN7UScbi0pzXrA==\",\n \"cpu\": [\n \"arm64\",\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/mac-x64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/mac-x64/-/mac-x64-3.15.1.tgz\",\n \"integrity\": \"sha512-NAetSQONxpNXTBnEo7oOkKZ84wO2avBy6V9vV9ntjJLb/07g7Rar8s/jVaicc/rVl6C+8ljZNwqJeynirgAC5w==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-arm64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-arm64/-/win-arm64-3.15.1.tgz\",\n \"integrity\": \"sha512-1O9tNSUgvgLL5hqgEuYiz7jRdA3+9yqzNJyPW1jExlQo442OA0eIpHBmeOtvXLwMkY7qv7wE75FdOPR7NVEnvg==\",\n \"cpu\": [\n \"arm64\",\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-x64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-x64/-/win-x64-3.15.1.tgz\",\n \"integrity\": \"sha512-jtoXBa6h+VPsQgefrO7HDjYv4WvxfHtUO30ABwCUDuEgM0e05YYhxMZj1z2Ns47UrquNvd/LUPCyjHKqHUN+5Q==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-x64-cuda\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-x64-cuda/-/win-x64-cuda-3.15.1.tgz\",\n \"integrity\": \"sha512-swoyx0/dY4ixiu3mEWrIAinx0ffHn9IncELDNREKG+iIXfx6w0OujOMQ6+X+lGj+sjE01yMUP/9fv6GEp2pmBw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-x64-cuda-ext\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-x64-cuda-ext/-/win-x64-cuda-ext-3.15.1.tgz\",\n \"integrity\": \"sha512-mO3Tf6D3UlFkjQF5J96ynTkjdF7dac/f5f61cEh6oU4D3hdx+cwnmBWT1gVhDSLboJYzCHtx7U2EKPP6n8HoWA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-x64-vulkan\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-x64-vulkan/-/win-x64-vulkan-3.15.1.tgz\",\n \"integrity\": \"sha512-BPBjUEIkFTdcHSsQyblP0v/aPPypi6uqQIq27mo4A49CYjX22JDmk4ncdBLk6cru+UkvwEEe+F2RomjoMt32aQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@octokit/app\": {\n \"version\": \"16.1.2\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/app/-/app-16.1.2.tgz\",\n \"integrity\": \"sha512-8j7sEpUYVj18dxvh0KWj6W/l6uAiVRBl1JBDVRqH1VHKAO/G5eRVl4yEoYACjakWers1DjUkcCHyJNQK47JqyQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-app\": \"^8.1.2\",\n \"@octokit/auth-unauthenticated\": \"^7.0.3\",\n \"@octokit/core\": \"^7.0.6\",\n \"@octokit/oauth-app\": \"^8.0.3\",\n \"@octokit/plugin-paginate-rest\": \"^14.0.0\",\n \"@octokit/types\": \"^16.0.0\",\n \"@octokit/webhooks\": \"^14.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-app\": {\n \"version\": \"8.2.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-app/-/auth-app-8.2.0.tgz\",\n \"integrity\": \"sha512-vVjdtQQwomrZ4V46B9LaCsxsySxGoHsyw6IYBov/TqJVROrlYdyNgw5q6tQbB7KZt53v1l1W53RiqTvpzL907g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-oauth-app\": \"^9.0.3\",\n \"@octokit/auth-oauth-user\": \"^6.0.2\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"toad-cache\": \"^3.7.0\",\n \"universal-github-app-jwt\": \"^2.2.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-oauth-app\": {\n \"version\": \"9.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-9.0.3.tgz\",\n \"integrity\": \"sha512-+yoFQquaF8OxJSxTb7rnytBIC2ZLbLqA/yb71I4ZXT9+Slw4TziV9j/kyGhUFRRTF2+7WlnIWsePZCWHs+OGjg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-oauth-device\": \"^8.0.3\",\n \"@octokit/auth-oauth-user\": \"^6.0.2\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-oauth-device\": {\n \"version\": \"8.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-8.0.3.tgz\",\n \"integrity\": \"sha512-zh2W0mKKMh/VWZhSqlaCzY7qFyrgd9oTWmTmHaXnHNeQRCZr/CXy2jCgHo4e4dJVTiuxP5dLa0YM5p5QVhJHbw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/oauth-methods\": \"^6.0.2\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-oauth-user\": {\n \"version\": \"6.0.2\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-6.0.2.tgz\",\n \"integrity\": \"sha512-qLoPPc6E6GJoz3XeDG/pnDhJpTkODTGG4kY0/Py154i/I003O9NazkrwJwRuzgCalhzyIeWQ+6MDvkUmKXjg/A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-oauth-device\": \"^8.0.3\",\n \"@octokit/oauth-methods\": \"^6.0.2\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-token\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz\",\n \"integrity\": \"sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-unauthenticated\": {\n \"version\": \"7.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-7.0.3.tgz\",\n \"integrity\": \"sha512-8Jb1mtUdmBHL7lGmop9mU9ArMRUTRhg8vp0T1VtZ4yd9vEm3zcLwmjQkhNEduKawOOORie61xhtYIhTDN+ZQ3g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/core\": {\n \"version\": \"7.0.6\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz\",\n \"integrity\": \"sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-token\": \"^6.0.0\",\n \"@octokit/graphql\": \"^9.0.3\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"before-after-hook\": \"^4.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/endpoint\": {\n \"version\": \"11.0.2\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.2.tgz\",\n \"integrity\": \"sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.2\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/graphql\": {\n \"version\": \"9.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz\",\n \"integrity\": \"sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/oauth-app\": {\n \"version\": \"8.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-8.0.3.tgz\",\n \"integrity\": \"sha512-jnAjvTsPepyUaMu9e69hYBuozEPgYqP4Z3UnpmvoIzHDpf8EXDGvTY1l1jK0RsZ194oRd+k6Hm13oRU8EoDFwg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-oauth-app\": \"^9.0.2\",\n \"@octokit/auth-oauth-user\": \"^6.0.1\",\n \"@octokit/auth-unauthenticated\": \"^7.0.2\",\n \"@octokit/core\": \"^7.0.5\",\n \"@octokit/oauth-authorization-url\": \"^8.0.0\",\n \"@octokit/oauth-methods\": \"^6.0.1\",\n \"@types/aws-lambda\": \"^8.10.83\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/oauth-authorization-url\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-8.0.0.tgz\",\n \"integrity\": \"sha512-7QoLPRh/ssEA/HuHBHdVdSgF8xNLz/Bc5m9fZkArJE5bb6NmVkDm3anKxXPmN1zh6b5WKZPRr3697xKT/yM3qQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/oauth-methods\": {\n \"version\": \"6.0.2\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-6.0.2.tgz\",\n \"integrity\": \"sha512-HiNOO3MqLxlt5Da5bZbLV8Zarnphi4y9XehrbaFMkcoJ+FL7sMxH/UlUsCVxpddVu4qvNDrBdaTVE2o4ITK8ng==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/oauth-authorization-url\": \"^8.0.0\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/openapi-types\": {\n \"version\": \"27.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz\",\n \"integrity\": \"sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/@octokit/openapi-webhooks-types\": {\n \"version\": \"12.1.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-12.1.0.tgz\",\n \"integrity\": \"sha512-WiuzhOsiOvb7W3Pvmhf8d2C6qaLHXrWiLBP4nJ/4kydu+wpagV5Fkz9RfQwV2afYzv3PB+3xYgp4mAdNGjDprA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/@octokit/plugin-paginate-graphql\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-6.0.0.tgz\",\n \"integrity\": \"sha512-crfpnIoFiBtRkvPqOyLOsw12XsveYuY2ieP6uYDosoUegBJpSVxGwut9sxUgFFcll3VTOTqpUf8yGd8x1OmAkQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \">=6\"\n }\n },\n \"node_modules/@octokit/plugin-paginate-rest\": {\n \"version\": \"14.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz\",\n \"integrity\": \"sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \">=6\"\n }\n },\n \"node_modules/@octokit/plugin-rest-endpoint-methods\": {\n \"version\": \"17.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz\",\n \"integrity\": \"sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \">=6\"\n }\n },\n \"node_modules/@octokit/plugin-retry\": {\n \"version\": \"8.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-8.0.3.tgz\",\n \"integrity\": \"sha512-vKGx1i3MC0za53IzYBSBXcrhmd+daQDzuZfYDd52X5S0M2otf3kVZTVP8bLA3EkU0lTvd1WEC2OlNNa4G+dohA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"bottleneck\": \"^2.15.3\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \">=7\"\n }\n },\n \"node_modules/@octokit/plugin-throttling\": {\n \"version\": \"11.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-11.0.3.tgz\",\n \"integrity\": \"sha512-34eE0RkFCKycLl2D2kq7W+LovheM/ex3AwZCYN8udpi6bxsyjZidb2McXs69hZhLmJlDqTSP8cH+jSRpiaijBg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\",\n \"bottleneck\": \"^2.15.3\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \"^7.0.0\"\n }\n },\n \"node_modules/@octokit/request\": {\n \"version\": \"10.0.7\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/request/-/request-10.0.7.tgz\",\n \"integrity\": \"sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/endpoint\": \"^11.0.2\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"fast-content-type-parse\": \"^3.0.0\",\n \"universal-user-agent\": \"^7.0.2\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/request-error\": {\n \"version\": \"7.1.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz\",\n \"integrity\": \"sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/types\": {\n \"version\": \"16.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz\",\n \"integrity\": \"sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/openapi-types\": \"^27.0.0\"\n }\n },\n \"node_modules/@octokit/webhooks\": {\n \"version\": \"14.2.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/webhooks/-/webhooks-14.2.0.tgz\",\n \"integrity\": \"sha512-da6KbdNCV5sr1/txD896V+6W0iamFWrvVl8cHkBSPT+YlvmT3DwXa4jxZnQc+gnuTEqSWbBeoSZYTayXH9wXcw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/openapi-webhooks-types\": \"12.1.0\",\n \"@octokit/request-error\": \"^7.0.0\",\n \"@octokit/webhooks-methods\": \"^6.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/webhooks-methods\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-6.0.0.tgz\",\n \"integrity\": \"sha512-MFlzzoDJVw/GcbfzVC1RLR36QqkTLUf79vLVO3D+xn7r0QgxnFoLZgtrzxiQErAjFUOdH6fas2KeQJ1yr/qaXQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@pkgjs/parseargs\": {\n \"version\": \"0.11.0\",\n \"resolved\": \"https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz\",\n \"integrity\": \"sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=14\"\n }\n },\n \"node_modules/@redis/bloom\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz\",\n \"integrity\": \"sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@redis/client\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz\",\n \"integrity\": \"sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"cluster-key-slot\": \"1.1.2\",\n \"generic-pool\": \"3.9.0\",\n \"yallist\": \"4.0.0\"\n },\n \"engines\": {\n \"node\": \">=14\"\n }\n },\n \"node_modules/@redis/graph\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz\",\n \"integrity\": \"sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@redis/json\": {\n \"version\": \"1.0.7\",\n \"resolved\": \"https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz\",\n \"integrity\": \"sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@redis/search\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz\",\n \"integrity\": \"sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@redis/time-series\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz\",\n \"integrity\": \"sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@reflink/reflink\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink/-/reflink-0.1.19.tgz\",\n \"integrity\": \"sha512-DmCG8GzysnCZ15bres3N5AHCmwBwYgp0As6xjhQ47rAUTUXxJiK+lLUxaGsX3hd/30qUpVElh05PbGuxRPgJwA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 10\"\n },\n \"optionalDependencies\": {\n \"@reflink/reflink-darwin-arm64\": \"0.1.19\",\n \"@reflink/reflink-darwin-x64\": \"0.1.19\",\n \"@reflink/reflink-linux-arm64-gnu\": \"0.1.19\",\n \"@reflink/reflink-linux-arm64-musl\": \"0.1.19\",\n \"@reflink/reflink-linux-x64-gnu\": \"0.1.19\",\n \"@reflink/reflink-linux-x64-musl\": \"0.1.19\",\n \"@reflink/reflink-win32-arm64-msvc\": \"0.1.19\",\n \"@reflink/reflink-win32-x64-msvc\": \"0.1.19\"\n }\n },\n \"node_modules/@reflink/reflink-darwin-arm64\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-darwin-arm64/-/reflink-darwin-arm64-0.1.19.tgz\",\n \"integrity\": \"sha512-ruy44Lpepdk1FqDz38vExBY/PVUsjxZA+chd9wozjUH9JjuDT/HEaQYA6wYN9mf041l0yLVar6BCZuWABJvHSA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-darwin-x64\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-darwin-x64/-/reflink-darwin-x64-0.1.19.tgz\",\n \"integrity\": \"sha512-By85MSWrMZa+c26TcnAy8SDk0sTUkYlNnwknSchkhHpGXOtjNDUOxJE9oByBnGbeuIE1PiQsxDG3Ud+IVV9yuA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-linux-arm64-gnu\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-linux-arm64-gnu/-/reflink-linux-arm64-gnu-0.1.19.tgz\",\n \"integrity\": \"sha512-7P+er8+rP9iNeN+bfmccM4hTAaLP6PQJPKWSA4iSk2bNvo6KU6RyPgYeHxXmzNKzPVRcypZQTpFgstHam6maVg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-linux-arm64-musl\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-linux-arm64-musl/-/reflink-linux-arm64-musl-0.1.19.tgz\",\n \"integrity\": \"sha512-37iO/Dp6m5DDaC2sf3zPtx/hl9FV3Xze4xoYidrxxS9bgP3S8ALroxRK6xBG/1TtfXKTvolvp+IjrUU6ujIGmA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-linux-x64-gnu\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-linux-x64-gnu/-/reflink-linux-x64-gnu-0.1.19.tgz\",\n \"integrity\": \"sha512-jbI8jvuYCaA3MVUdu8vLoLAFqC+iNMpiSuLbxlAgg7x3K5bsS8nOpTRnkLF7vISJ+rVR8W+7ThXlXlUQ93ulkw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-linux-x64-musl\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-linux-x64-musl/-/reflink-linux-x64-musl-0.1.19.tgz\",\n \"integrity\": \"sha512-e9FBWDe+lv7QKAwtKOt6A2W/fyy/aEEfr0g6j/hWzvQcrzHCsz07BNQYlNOjTfeytrtLU7k449H1PI95jA4OjQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-win32-arm64-msvc\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-win32-arm64-msvc/-/reflink-win32-arm64-msvc-0.1.19.tgz\",\n \"integrity\": \"sha512-09PxnVIQcd+UOn4WAW73WU6PXL7DwGS6wPlkMhMg2zlHHG65F3vHepOw06HFCq+N42qkaNAc8AKIabWvtk6cIQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-win32-x64-msvc\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-win32-x64-msvc/-/reflink-win32-x64-msvc-0.1.19.tgz\",\n \"integrity\": \"sha512-E//yT4ni2SyhwP8JRjVGWr3cbnhWDiPLgnQ66qqaanjjnMiu3O/2tjCPQXlcGc/DEYofpDc9fvhv6tALQsMV9w==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@rollup/rollup-android-arm-eabi\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz\",\n \"integrity\": \"sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ]\n },\n \"node_modules/@rollup/rollup-android-arm64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz\",\n \"integrity\": \"sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ]\n },\n \"node_modules/@rollup/rollup-darwin-arm64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz\",\n \"integrity\": \"sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ]\n },\n \"node_modules/@rollup/rollup-darwin-x64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz\",\n \"integrity\": \"sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ]\n },\n \"node_modules/@rollup/rollup-freebsd-arm64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz\",\n \"integrity\": \"sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ]\n },\n \"node_modules/@rollup/rollup-freebsd-x64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz\",\n \"integrity\": \"sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-arm-gnueabihf\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz\",\n \"integrity\": \"sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-arm-musleabihf\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz\",\n \"integrity\": \"sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-arm64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-arm64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-loong64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==\",\n \"cpu\": [\n \"loong64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-loong64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==\",\n \"cpu\": [\n \"loong64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-ppc64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-ppc64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-riscv64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==\",\n \"cpu\": [\n \"riscv64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-riscv64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==\",\n \"cpu\": [\n \"riscv64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-s390x-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==\",\n \"cpu\": [\n \"s390x\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-x64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-x64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-openbsd-x64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz\",\n \"integrity\": \"sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openbsd\"\n ]\n },\n \"node_modules/@rollup/rollup-openharmony-arm64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz\",\n \"integrity\": \"sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openharmony\"\n ]\n },\n \"node_modules/@rollup/rollup-win32-arm64-msvc\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz\",\n \"integrity\": \"sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/@rollup/rollup-win32-ia32-msvc\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz\",\n \"integrity\": \"sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/@rollup/rollup-win32-x64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/@rollup/rollup-win32-x64-msvc\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz\",\n \"integrity\": \"sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/@sinclair/typebox\": {\n \"version\": \"0.27.8\",\n \"resolved\": \"https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz\",\n \"integrity\": \"sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@tinyhttp/content-disposition\": {\n \"version\": \"2.2.4\",\n \"resolved\": \"https://registry.npmjs.org/@tinyhttp/content-disposition/-/content-disposition-2.2.4.tgz\",\n \"integrity\": \"sha512-5Kc5CM2Ysn3vTTArBs2vESUt0AQiWZA86yc1TI3B+lxXmtEq133C1nxXNOgnzhrivdPZIh3zLj5gDnZjoLL5GA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12.17.0\"\n },\n \"funding\": {\n \"type\": \"individual\",\n \"url\": \"https://github.com/tinyhttp/tinyhttp?sponsor=1\"\n }\n },\n \"node_modules/@types/aws-lambda\": {\n \"version\": \"8.10.160\",\n \"resolved\": \"https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.160.tgz\",\n \"integrity\": \"sha512-uoO4QVQNWFPJMh26pXtmtrRfGshPUSpMZGUyUQY20FhfHEElEBOPKgVmFs1z+kbpyBsRs2JnoOPT7++Z4GA9pA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/@types/estree\": {\n \"version\": \"1.0.8\",\n \"resolved\": \"https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz\",\n \"integrity\": \"sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@types/node\": {\n \"version\": \"20.19.30\",\n \"resolved\": \"https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz\",\n \"integrity\": \"sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"undici-types\": \"~6.21.0\"\n }\n },\n \"node_modules/@types/webidl-conversions\": {\n \"version\": \"7.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz\",\n \"integrity\": \"sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==\",\n \"license\": \"MIT\"\n },\n \"node_modules/@types/whatwg-url\": {\n \"version\": \"11.0.5\",\n \"resolved\": \"https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz\",\n \"integrity\": \"sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@types/webidl-conversions\": \"*\"\n }\n },\n \"node_modules/@vitest/expect\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz\",\n \"integrity\": \"sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@vitest/spy\": \"1.6.1\",\n \"@vitest/utils\": \"1.6.1\",\n \"chai\": \"^4.3.10\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/@vitest/runner\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/runner/-/runner-1.6.1.tgz\",\n \"integrity\": \"sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@vitest/utils\": \"1.6.1\",\n \"p-limit\": \"^5.0.0\",\n \"pathe\": \"^1.1.1\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/@vitest/runner/node_modules/pathe\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz\",\n \"integrity\": \"sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@vitest/snapshot\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.1.tgz\",\n \"integrity\": \"sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"magic-string\": \"^0.30.5\",\n \"pathe\": \"^1.1.1\",\n \"pretty-format\": \"^29.7.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/@vitest/snapshot/node_modules/pathe\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz\",\n \"integrity\": \"sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@vitest/spy\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/spy/-/spy-1.6.1.tgz\",\n \"integrity\": \"sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"tinyspy\": \"^2.2.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/@vitest/utils\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/utils/-/utils-1.6.1.tgz\",\n \"integrity\": \"sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"diff-sequences\": \"^29.6.3\",\n \"estree-walker\": \"^3.0.3\",\n \"loupe\": \"^2.3.7\",\n \"pretty-format\": \"^29.7.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/accepts\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz\",\n \"integrity\": \"sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"mime-types\": \"^3.0.0\",\n \"negotiator\": \"^1.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/acorn\": {\n \"version\": \"8.15.0\",\n \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz\",\n \"integrity\": \"sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"bin\": {\n \"acorn\": \"bin/acorn\"\n },\n \"engines\": {\n \"node\": \">=0.4.0\"\n }\n },\n \"node_modules/acorn-walk\": {\n \"version\": \"8.3.4\",\n \"resolved\": \"https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz\",\n \"integrity\": \"sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"acorn\": \"^8.11.0\"\n },\n \"engines\": {\n \"node\": \">=0.4.0\"\n }\n },\n \"node_modules/afinn-165\": {\n \"version\": \"1.0.4\",\n \"resolved\": \"https://registry.npmjs.org/afinn-165/-/afinn-165-1.0.4.tgz\",\n \"integrity\": \"sha512-7+Wlx3BImrK0HiG6y3lU4xX7SpBPSSu8T9iguPMlaueRFxjbYwAQrp9lqZUuFikqKbd/en8lVREILvP2J80uJA==\",\n \"license\": \"MIT\",\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/wooorm\"\n }\n },\n \"node_modules/afinn-165-financialmarketnews\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/afinn-165-financialmarketnews/-/afinn-165-financialmarketnews-3.0.0.tgz\",\n \"integrity\": \"sha512-0g9A1S3ZomFIGDTzZ0t6xmv4AuokBvBmpes8htiyHpH7N4xDmvSQL6UxL/Zcs2ypRb3VwgCscaD8Q3zEawKYhw==\",\n \"license\": \"MIT\",\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/wooorm\"\n }\n },\n \"node_modules/ajv\": {\n \"version\": \"8.17.1\",\n \"resolved\": \"https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz\",\n \"integrity\": \"sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"fast-deep-equal\": \"^3.1.3\",\n \"fast-uri\": \"^3.0.1\",\n \"json-schema-traverse\": \"^1.0.0\",\n \"require-from-string\": \"^2.0.2\"\n },\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/epoberezkin\"\n }\n },\n \"node_modules/ajv-formats\": {\n \"version\": \"3.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz\",\n \"integrity\": \"sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ajv\": \"^8.0.0\"\n },\n \"peerDependencies\": {\n \"ajv\": \"^8.0.0\"\n },\n \"peerDependenciesMeta\": {\n \"ajv\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/ansi-escapes\": {\n \"version\": \"6.2.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz\",\n \"integrity\": \"sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=14.16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ansi-regex\": {\n \"version\": \"6.2.2\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz\",\n \"integrity\": \"sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-regex?sponsor=1\"\n }\n },\n \"node_modules/ansi-styles\": {\n \"version\": \"5.2.0\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz\",\n \"integrity\": \"sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=10\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/any-promise\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz\",\n \"integrity\": \"sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/apparatus\": {\n \"version\": \"0.0.10\",\n \"resolved\": \"https://registry.npmjs.org/apparatus/-/apparatus-0.0.10.tgz\",\n \"integrity\": \"sha512-KLy/ugo33KZA7nugtQ7O0E1c8kQ52N3IvD/XgIh4w/Nr28ypfkwDfA67F1ev4N1m5D+BOk1+b2dEJDfpj/VvZg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"sylvester\": \">= 0.0.8\"\n },\n \"engines\": {\n \"node\": \">=0.2.6\"\n }\n },\n \"node_modules/aproba\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz\",\n \"integrity\": \"sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/are-we-there-yet\": {\n \"version\": \"3.0.1\",\n \"resolved\": \"https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz\",\n \"integrity\": \"sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==\",\n \"deprecated\": \"This package is no longer supported.\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"delegates\": \"^1.0.0\",\n \"readable-stream\": \"^3.6.0\"\n },\n \"engines\": {\n \"node\": \"^12.13.0 || ^14.15.0 || >=16.0.0\"\n }\n },\n \"node_modules/argparse\": {\n \"version\": \"1.0.10\",\n \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz\",\n \"integrity\": \"sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"sprintf-js\": \"~1.0.2\"\n }\n },\n \"node_modules/assertion-error\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz\",\n \"integrity\": \"sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"*\"\n }\n },\n \"node_modules/async-retry\": {\n \"version\": \"1.3.3\",\n \"resolved\": \"https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz\",\n \"integrity\": \"sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"retry\": \"0.13.1\"\n }\n },\n \"node_modules/asynckit\": {\n \"version\": \"0.4.0\",\n \"resolved\": \"https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz\",\n \"integrity\": \"sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/axios\": {\n \"version\": \"1.13.4\",\n \"resolved\": \"https://registry.npmjs.org/axios/-/axios-1.13.4.tgz\",\n \"integrity\": \"sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"follow-redirects\": \"^1.15.6\",\n \"form-data\": \"^4.0.4\",\n \"proxy-from-env\": \"^1.1.0\"\n }\n },\n \"node_modules/balanced-match\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz\",\n \"integrity\": \"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==\",\n \"license\": \"MIT\"\n },\n \"node_modules/before-after-hook\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz\",\n \"integrity\": \"sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==\",\n \"license\": \"Apache-2.0\",\n \"optional\": true\n },\n \"node_modules/body-parser\": {\n \"version\": \"2.2.2\",\n \"resolved\": \"https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz\",\n \"integrity\": \"sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"bytes\": \"^3.1.2\",\n \"content-type\": \"^1.0.5\",\n \"debug\": \"^4.4.3\",\n \"http-errors\": \"^2.0.0\",\n \"iconv-lite\": \"^0.7.0\",\n \"on-finished\": \"^2.4.1\",\n \"qs\": \"^6.14.1\",\n \"raw-body\": \"^3.0.1\",\n \"type-is\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/bottleneck\": {\n \"version\": \"2.19.5\",\n \"resolved\": \"https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz\",\n \"integrity\": \"sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/brace-expansion\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz\",\n \"integrity\": \"sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"balanced-match\": \"^1.0.0\"\n }\n },\n \"node_modules/bson\": {\n \"version\": \"6.10.4\",\n \"resolved\": \"https://registry.npmjs.org/bson/-/bson-6.10.4.tgz\",\n \"integrity\": \"sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==\",\n \"license\": \"Apache-2.0\",\n \"engines\": {\n \"node\": \">=16.20.1\"\n }\n },\n \"node_modules/bundle-require\": {\n \"version\": \"5.1.0\",\n \"resolved\": \"https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz\",\n \"integrity\": \"sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"load-tsconfig\": \"^0.2.3\"\n },\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n },\n \"peerDependencies\": {\n \"esbuild\": \">=0.18\"\n }\n },\n \"node_modules/bytes\": {\n \"version\": \"3.1.2\",\n \"resolved\": \"https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz\",\n \"integrity\": \"sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/cac\": {\n \"version\": \"6.7.14\",\n \"resolved\": \"https://registry.npmjs.org/cac/-/cac-6.7.14.tgz\",\n \"integrity\": \"sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/call-bind-apply-helpers\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz\",\n \"integrity\": \"sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\",\n \"function-bind\": \"^1.1.2\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/call-bound\": {\n \"version\": \"1.0.4\",\n \"resolved\": \"https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz\",\n \"integrity\": \"sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bind-apply-helpers\": \"^1.0.2\",\n \"get-intrinsic\": \"^1.3.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/chai\": {\n \"version\": \"4.5.0\",\n \"resolved\": \"https://registry.npmjs.org/chai/-/chai-4.5.0.tgz\",\n \"integrity\": \"sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"assertion-error\": \"^1.1.0\",\n \"check-error\": \"^1.0.3\",\n \"deep-eql\": \"^4.1.3\",\n \"get-func-name\": \"^2.0.2\",\n \"loupe\": \"^2.3.6\",\n \"pathval\": \"^1.1.1\",\n \"type-detect\": \"^4.1.0\"\n },\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/chalk\": {\n \"version\": \"5.6.2\",\n \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz\",\n \"integrity\": \"sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^12.17.0 || ^14.13 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/chalk?sponsor=1\"\n }\n },\n \"node_modules/check-error\": {\n \"version\": \"1.0.3\",\n \"resolved\": \"https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz\",\n \"integrity\": \"sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"get-func-name\": \"^2.0.2\"\n },\n \"engines\": {\n \"node\": \"*\"\n }\n },\n \"node_modules/chmodrp\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/chmodrp/-/chmodrp-1.0.2.tgz\",\n \"integrity\": \"sha512-TdngOlFV1FLTzU0o1w8MB6/BFywhtLC0SzRTGJU7T9lmdjlCWeMRt1iVo0Ki+ldwNk0BqNiKoc8xpLZEQ8mY1w==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/chokidar\": {\n \"version\": \"4.0.3\",\n \"resolved\": \"https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz\",\n \"integrity\": \"sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"readdirp\": \"^4.0.1\"\n },\n \"engines\": {\n \"node\": \">= 14.16.0\"\n },\n \"funding\": {\n \"url\": \"https://paulmillr.com/funding/\"\n }\n },\n \"node_modules/chownr\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz\",\n \"integrity\": \"sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/ci-info\": {\n \"version\": \"4.4.0\",\n \"resolved\": \"https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz\",\n \"integrity\": \"sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/sibiraj-s\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/cli-cursor\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz\",\n \"integrity\": \"sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"restore-cursor\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/cli-spinners\": {\n \"version\": \"2.9.2\",\n \"resolved\": \"https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz\",\n \"integrity\": \"sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=6\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/cliui\": {\n \"version\": \"8.0.1\",\n \"resolved\": \"https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz\",\n \"integrity\": \"sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"string-width\": \"^4.2.0\",\n \"strip-ansi\": \"^6.0.1\",\n \"wrap-ansi\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/cliui/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/cliui/node_modules/ansi-styles\": {\n \"version\": \"4.3.0\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz\",\n \"integrity\": \"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"color-convert\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/cliui/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/cliui/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/cliui/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/cliui/node_modules/wrap-ansi\": {\n \"version\": \"7.0.0\",\n \"resolved\": \"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz\",\n \"integrity\": \"sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-styles\": \"^4.0.0\",\n \"string-width\": \"^4.1.0\",\n \"strip-ansi\": \"^6.0.0\"\n },\n \"engines\": {\n \"node\": \">=10\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/wrap-ansi?sponsor=1\"\n }\n },\n \"node_modules/cluster-key-slot\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz\",\n \"integrity\": \"sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==\",\n \"license\": \"Apache-2.0\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/cmake-js\": {\n \"version\": \"7.4.0\",\n \"resolved\": \"https://registry.npmjs.org/cmake-js/-/cmake-js-7.4.0.tgz\",\n \"integrity\": \"sha512-Lw0JxEHrmk+qNj1n9W9d4IvkDdYTBn7l2BW6XmtLj7WPpIo2shvxUy+YokfjMxAAOELNonQwX3stkPhM5xSC2Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"axios\": \"^1.6.5\",\n \"debug\": \"^4\",\n \"fs-extra\": \"^11.2.0\",\n \"memory-stream\": \"^1.0.0\",\n \"node-api-headers\": \"^1.1.0\",\n \"npmlog\": \"^6.0.2\",\n \"rc\": \"^1.2.7\",\n \"semver\": \"^7.5.4\",\n \"tar\": \"^6.2.0\",\n \"url-join\": \"^4.0.1\",\n \"which\": \"^2.0.2\",\n \"yargs\": \"^17.7.2\"\n },\n \"bin\": {\n \"cmake-js\": \"bin/cmake-js\"\n },\n \"engines\": {\n \"node\": \">= 14.15.0\"\n }\n },\n \"node_modules/color-convert\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz\",\n \"integrity\": \"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"color-name\": \"~1.1.4\"\n },\n \"engines\": {\n \"node\": \">=7.0.0\"\n }\n },\n \"node_modules/color-name\": {\n \"version\": \"1.1.4\",\n \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz\",\n \"integrity\": \"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==\",\n \"license\": \"MIT\"\n },\n \"node_modules/color-support\": {\n \"version\": \"1.1.3\",\n \"resolved\": \"https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz\",\n \"integrity\": \"sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"bin\": {\n \"color-support\": \"bin.js\"\n }\n },\n \"node_modules/combined-stream\": {\n \"version\": \"1.0.8\",\n \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz\",\n \"integrity\": \"sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"delayed-stream\": \"~1.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/commander\": {\n \"version\": \"12.1.0\",\n \"resolved\": \"https://registry.npmjs.org/commander/-/commander-12.1.0.tgz\",\n \"integrity\": \"sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/confbox\": {\n \"version\": \"0.1.8\",\n \"resolved\": \"https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz\",\n \"integrity\": \"sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/consola\": {\n \"version\": \"3.4.2\",\n \"resolved\": \"https://registry.npmjs.org/consola/-/consola-3.4.2.tgz\",\n \"integrity\": \"sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^14.18.0 || >=16.10.0\"\n }\n },\n \"node_modules/console-control-strings\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz\",\n \"integrity\": \"sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/content-disposition\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz\",\n \"integrity\": \"sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/content-type\": {\n \"version\": \"1.0.5\",\n \"resolved\": \"https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz\",\n \"integrity\": \"sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/cookie\": {\n \"version\": \"0.7.2\",\n \"resolved\": \"https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz\",\n \"integrity\": \"sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/cookie-signature\": {\n \"version\": \"1.2.2\",\n \"resolved\": \"https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz\",\n \"integrity\": \"sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=6.6.0\"\n }\n },\n \"node_modules/cors\": {\n \"version\": \"2.8.6\",\n \"resolved\": \"https://registry.npmjs.org/cors/-/cors-2.8.6.tgz\",\n \"integrity\": \"sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"object-assign\": \"^4\",\n \"vary\": \"^1\"\n },\n \"engines\": {\n \"node\": \">= 0.10\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/cross-spawn\": {\n \"version\": \"7.0.6\",\n \"resolved\": \"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz\",\n \"integrity\": \"sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"path-key\": \"^3.1.0\",\n \"shebang-command\": \"^2.0.0\",\n \"which\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">= 8\"\n }\n },\n \"node_modules/debug\": {\n \"version\": \"4.4.3\",\n \"resolved\": \"https://registry.npmjs.org/debug/-/debug-4.4.3.tgz\",\n \"integrity\": \"sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ms\": \"^2.1.3\"\n },\n \"engines\": {\n \"node\": \">=6.0\"\n },\n \"peerDependenciesMeta\": {\n \"supports-color\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/deep-eql\": {\n \"version\": \"4.1.4\",\n \"resolved\": \"https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz\",\n \"integrity\": \"sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"type-detect\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=6\"\n }\n },\n \"node_modules/deep-extend\": {\n \"version\": \"0.6.0\",\n \"resolved\": \"https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz\",\n \"integrity\": \"sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=4.0.0\"\n }\n },\n \"node_modules/delayed-stream\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\",\n \"integrity\": \"sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.4.0\"\n }\n },\n \"node_modules/delegates\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz\",\n \"integrity\": \"sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/depd\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/depd/-/depd-2.0.0.tgz\",\n \"integrity\": \"sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/diff-sequences\": {\n \"version\": \"29.6.3\",\n \"resolved\": \"https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz\",\n \"integrity\": \"sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^14.15.0 || ^16.10.0 || >=18.0.0\"\n }\n },\n \"node_modules/dotenv\": {\n \"version\": \"16.6.1\",\n \"resolved\": \"https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz\",\n \"integrity\": \"sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==\",\n \"license\": \"BSD-2-Clause\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://dotenvx.com\"\n }\n },\n \"node_modules/dunder-proto\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz\",\n \"integrity\": \"sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bind-apply-helpers\": \"^1.0.1\",\n \"es-errors\": \"^1.3.0\",\n \"gopd\": \"^1.2.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/eastasianwidth\": {\n \"version\": \"0.2.0\",\n \"resolved\": \"https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz\",\n \"integrity\": \"sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==\",\n \"license\": \"MIT\"\n },\n \"node_modules/ee-first\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\",\n \"integrity\": \"sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/emoji-regex\": {\n \"version\": \"9.2.2\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz\",\n \"integrity\": \"sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==\",\n \"license\": \"MIT\"\n },\n \"node_modules/encodeurl\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz\",\n \"integrity\": \"sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/env-var\": {\n \"version\": \"7.5.0\",\n \"resolved\": \"https://registry.npmjs.org/env-var/-/env-var-7.5.0.tgz\",\n \"integrity\": \"sha512-mKZOzLRN0ETzau2W2QXefbFjo5EF4yWq28OyKb9ICdeNhHJlOE/pHHnz4hdYJ9cNZXcJHo5xN4OT4pzuSHSNvA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/es-define-property\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz\",\n \"integrity\": \"sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/es-errors\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz\",\n \"integrity\": \"sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/es-object-atoms\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz\",\n \"integrity\": \"sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/es-set-tostringtag\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz\",\n \"integrity\": \"sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\",\n \"get-intrinsic\": \"^1.2.6\",\n \"has-tostringtag\": \"^1.0.2\",\n \"hasown\": \"^2.0.2\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/esbuild\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz\",\n \"integrity\": \"sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==\",\n \"dev\": true,\n \"hasInstallScript\": true,\n \"license\": \"MIT\",\n \"bin\": {\n \"esbuild\": \"bin/esbuild\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"optionalDependencies\": {\n \"@esbuild/aix-ppc64\": \"0.27.2\",\n \"@esbuild/android-arm\": \"0.27.2\",\n \"@esbuild/android-arm64\": \"0.27.2\",\n \"@esbuild/android-x64\": \"0.27.2\",\n \"@esbuild/darwin-arm64\": \"0.27.2\",\n \"@esbuild/darwin-x64\": \"0.27.2\",\n \"@esbuild/freebsd-arm64\": \"0.27.2\",\n \"@esbuild/freebsd-x64\": \"0.27.2\",\n \"@esbuild/linux-arm\": \"0.27.2\",\n \"@esbuild/linux-arm64\": \"0.27.2\",\n \"@esbuild/linux-ia32\": \"0.27.2\",\n \"@esbuild/linux-loong64\": \"0.27.2\",\n \"@esbuild/linux-mips64el\": \"0.27.2\",\n \"@esbuild/linux-ppc64\": \"0.27.2\",\n \"@esbuild/linux-riscv64\": \"0.27.2\",\n \"@esbuild/linux-s390x\": \"0.27.2\",\n \"@esbuild/linux-x64\": \"0.27.2\",\n \"@esbuild/netbsd-arm64\": \"0.27.2\",\n \"@esbuild/netbsd-x64\": \"0.27.2\",\n \"@esbuild/openbsd-arm64\": \"0.27.2\",\n \"@esbuild/openbsd-x64\": \"0.27.2\",\n \"@esbuild/openharmony-arm64\": \"0.27.2\",\n \"@esbuild/sunos-x64\": \"0.27.2\",\n \"@esbuild/win32-arm64\": \"0.27.2\",\n \"@esbuild/win32-ia32\": \"0.27.2\",\n \"@esbuild/win32-x64\": \"0.27.2\"\n }\n },\n \"node_modules/escalade\": {\n \"version\": \"3.2.0\",\n \"resolved\": \"https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz\",\n \"integrity\": \"sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=6\"\n }\n },\n \"node_modules/escape-html\": {\n \"version\": \"1.0.3\",\n \"resolved\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz\",\n \"integrity\": \"sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/esprima\": {\n \"version\": \"4.0.1\",\n \"resolved\": \"https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz\",\n \"integrity\": \"sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==\",\n \"license\": \"BSD-2-Clause\",\n \"bin\": {\n \"esparse\": \"bin/esparse.js\",\n \"esvalidate\": \"bin/esvalidate.js\"\n },\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/estree-walker\": {\n \"version\": \"3.0.3\",\n \"resolved\": \"https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz\",\n \"integrity\": \"sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@types/estree\": \"^1.0.0\"\n }\n },\n \"node_modules/etag\": {\n \"version\": \"1.8.1\",\n \"resolved\": \"https://registry.npmjs.org/etag/-/etag-1.8.1.tgz\",\n \"integrity\": \"sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/eventemitter3\": {\n \"version\": \"5.0.4\",\n \"resolved\": \"https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz\",\n \"integrity\": \"sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/eventsource\": {\n \"version\": \"3.0.7\",\n \"resolved\": \"https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz\",\n \"integrity\": \"sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"eventsource-parser\": \"^3.0.1\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n },\n \"node_modules/eventsource-parser\": {\n \"version\": \"3.0.6\",\n \"resolved\": \"https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz\",\n \"integrity\": \"sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n },\n \"node_modules/execa\": {\n \"version\": \"8.0.1\",\n \"resolved\": \"https://registry.npmjs.org/execa/-/execa-8.0.1.tgz\",\n \"integrity\": \"sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"cross-spawn\": \"^7.0.3\",\n \"get-stream\": \"^8.0.1\",\n \"human-signals\": \"^5.0.0\",\n \"is-stream\": \"^3.0.0\",\n \"merge-stream\": \"^2.0.0\",\n \"npm-run-path\": \"^5.1.0\",\n \"onetime\": \"^6.0.0\",\n \"signal-exit\": \"^4.1.0\",\n \"strip-final-newline\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">=16.17\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sindresorhus/execa?sponsor=1\"\n }\n },\n \"node_modules/express\": {\n \"version\": \"5.2.1\",\n \"resolved\": \"https://registry.npmjs.org/express/-/express-5.2.1.tgz\",\n \"integrity\": \"sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"accepts\": \"^2.0.0\",\n \"body-parser\": \"^2.2.1\",\n \"content-disposition\": \"^1.0.0\",\n \"content-type\": \"^1.0.5\",\n \"cookie\": \"^0.7.1\",\n \"cookie-signature\": \"^1.2.1\",\n \"debug\": \"^4.4.0\",\n \"depd\": \"^2.0.0\",\n \"encodeurl\": \"^2.0.0\",\n \"escape-html\": \"^1.0.3\",\n \"etag\": \"^1.8.1\",\n \"finalhandler\": \"^2.1.0\",\n \"fresh\": \"^2.0.0\",\n \"http-errors\": \"^2.0.0\",\n \"merge-descriptors\": \"^2.0.0\",\n \"mime-types\": \"^3.0.0\",\n \"on-finished\": \"^2.4.1\",\n \"once\": \"^1.4.0\",\n \"parseurl\": \"^1.3.3\",\n \"proxy-addr\": \"^2.0.7\",\n \"qs\": \"^6.14.0\",\n \"range-parser\": \"^1.2.1\",\n \"router\": \"^2.2.0\",\n \"send\": \"^1.1.0\",\n \"serve-static\": \"^2.2.0\",\n \"statuses\": \"^2.0.1\",\n \"type-is\": \"^2.0.1\",\n \"vary\": \"^1.1.2\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/express-rate-limit\": {\n \"version\": \"7.5.1\",\n \"resolved\": \"https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz\",\n \"integrity\": \"sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/express-rate-limit\"\n },\n \"peerDependencies\": {\n \"express\": \">= 4.11\"\n }\n },\n \"node_modules/extend-shallow\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz\",\n \"integrity\": \"sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"is-extendable\": \"^0.1.0\"\n },\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/fast-content-type-parse\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz\",\n \"integrity\": \"sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/fastify\"\n },\n {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/fastify\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/fast-deep-equal\": {\n \"version\": \"3.1.3\",\n \"resolved\": \"https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz\",\n \"integrity\": \"sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/fast-uri\": {\n \"version\": \"3.1.0\",\n \"resolved\": \"https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz\",\n \"integrity\": \"sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/fastify\"\n },\n {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/fastify\"\n }\n ],\n \"license\": \"BSD-3-Clause\",\n \"optional\": true\n },\n \"node_modules/fdir\": {\n \"version\": \"6.5.0\",\n \"resolved\": \"https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz\",\n \"integrity\": \"sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12.0.0\"\n },\n \"peerDependencies\": {\n \"picomatch\": \"^3 || ^4\"\n },\n \"peerDependenciesMeta\": {\n \"picomatch\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/filename-reserved-regex\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz\",\n \"integrity\": \"sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/filenamify\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz\",\n \"integrity\": \"sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"filename-reserved-regex\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">=16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/finalhandler\": {\n \"version\": \"2.1.1\",\n \"resolved\": \"https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz\",\n \"integrity\": \"sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"debug\": \"^4.4.0\",\n \"encodeurl\": \"^2.0.0\",\n \"escape-html\": \"^1.0.3\",\n \"on-finished\": \"^2.4.1\",\n \"parseurl\": \"^1.3.3\",\n \"statuses\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">= 18.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/fix-dts-default-cjs-exports\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz\",\n \"integrity\": \"sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"magic-string\": \"^0.30.17\",\n \"mlly\": \"^1.7.4\",\n \"rollup\": \"^4.34.8\"\n }\n },\n \"node_modules/follow-redirects\": {\n \"version\": \"1.15.11\",\n \"resolved\": \"https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz\",\n \"integrity\": \"sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==\",\n \"funding\": [\n {\n \"type\": \"individual\",\n \"url\": \"https://github.com/sponsors/RubenVerborgh\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=4.0\"\n },\n \"peerDependenciesMeta\": {\n \"debug\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/foreground-child\": {\n \"version\": \"3.3.1\",\n \"resolved\": \"https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz\",\n \"integrity\": \"sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"cross-spawn\": \"^7.0.6\",\n \"signal-exit\": \"^4.0.1\"\n },\n \"engines\": {\n \"node\": \">=14\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/form-data\": {\n \"version\": \"4.0.5\",\n \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz\",\n \"integrity\": \"sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"asynckit\": \"^0.4.0\",\n \"combined-stream\": \"^1.0.8\",\n \"es-set-tostringtag\": \"^2.1.0\",\n \"hasown\": \"^2.0.2\",\n \"mime-types\": \"^2.1.12\"\n },\n \"engines\": {\n \"node\": \">= 6\"\n }\n },\n \"node_modules/form-data/node_modules/mime-db\": {\n \"version\": \"1.52.0\",\n \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz\",\n \"integrity\": \"sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/form-data/node_modules/mime-types\": {\n \"version\": \"2.1.35\",\n \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz\",\n \"integrity\": \"sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"mime-db\": \"1.52.0\"\n },\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/forwarded\": {\n \"version\": \"0.2.0\",\n \"resolved\": \"https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz\",\n \"integrity\": \"sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/fresh\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz\",\n \"integrity\": \"sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/fs-extra\": {\n \"version\": \"11.3.3\",\n \"resolved\": \"https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz\",\n \"integrity\": \"sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"graceful-fs\": \"^4.2.0\",\n \"jsonfile\": \"^6.0.1\",\n \"universalify\": \"^2.0.0\"\n },\n \"engines\": {\n \"node\": \">=14.14\"\n }\n },\n \"node_modules/fs-minipass\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz\",\n \"integrity\": \"sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"minipass\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">= 8\"\n }\n },\n \"node_modules/fs-minipass/node_modules/minipass\": {\n \"version\": \"3.3.6\",\n \"resolved\": \"https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz\",\n \"integrity\": \"sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"yallist\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/fsevents\": {\n \"version\": \"2.3.3\",\n \"resolved\": \"https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz\",\n \"integrity\": \"sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==\",\n \"dev\": true,\n \"hasInstallScript\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \"^8.16.0 || ^10.6.0 || >=11.0.0\"\n }\n },\n \"node_modules/function-bind\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz\",\n \"integrity\": \"sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/gauge\": {\n \"version\": \"4.0.4\",\n \"resolved\": \"https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz\",\n \"integrity\": \"sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==\",\n \"deprecated\": \"This package is no longer supported.\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"aproba\": \"^1.0.3 || ^2.0.0\",\n \"color-support\": \"^1.1.3\",\n \"console-control-strings\": \"^1.1.0\",\n \"has-unicode\": \"^2.0.1\",\n \"signal-exit\": \"^3.0.7\",\n \"string-width\": \"^4.2.3\",\n \"strip-ansi\": \"^6.0.1\",\n \"wide-align\": \"^1.1.5\"\n },\n \"engines\": {\n \"node\": \"^12.13.0 || ^14.15.0 || >=16.0.0\"\n }\n },\n \"node_modules/gauge/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/gauge/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/gauge/node_modules/signal-exit\": {\n \"version\": \"3.0.7\",\n \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz\",\n \"integrity\": \"sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/gauge/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/gauge/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/generic-pool\": {\n \"version\": \"3.9.0\",\n \"resolved\": \"https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz\",\n \"integrity\": \"sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">= 4\"\n }\n },\n \"node_modules/get-caller-file\": {\n \"version\": \"2.0.5\",\n \"resolved\": \"https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz\",\n \"integrity\": \"sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"6.* || 8.* || >= 10.*\"\n }\n },\n \"node_modules/get-east-asian-width\": {\n \"version\": \"1.4.0\",\n \"resolved\": \"https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz\",\n \"integrity\": \"sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/get-func-name\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz\",\n \"integrity\": \"sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"*\"\n }\n },\n \"node_modules/get-intrinsic\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz\",\n \"integrity\": \"sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bind-apply-helpers\": \"^1.0.2\",\n \"es-define-property\": \"^1.0.1\",\n \"es-errors\": \"^1.3.0\",\n \"es-object-atoms\": \"^1.1.1\",\n \"function-bind\": \"^1.1.2\",\n \"get-proto\": \"^1.0.1\",\n \"gopd\": \"^1.2.0\",\n \"has-symbols\": \"^1.1.0\",\n \"hasown\": \"^2.0.2\",\n \"math-intrinsics\": \"^1.1.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/get-proto\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz\",\n \"integrity\": \"sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"dunder-proto\": \"^1.0.1\",\n \"es-object-atoms\": \"^1.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/get-stream\": {\n \"version\": \"8.0.1\",\n \"resolved\": \"https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz\",\n \"integrity\": \"sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/glob\": {\n \"version\": \"10.5.0\",\n \"resolved\": \"https://registry.npmjs.org/glob/-/glob-10.5.0.tgz\",\n \"integrity\": \"sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"foreground-child\": \"^3.1.0\",\n \"jackspeak\": \"^3.1.2\",\n \"minimatch\": \"^9.0.4\",\n \"minipass\": \"^7.1.2\",\n \"package-json-from-dist\": \"^1.0.0\",\n \"path-scurry\": \"^1.11.1\"\n },\n \"bin\": {\n \"glob\": \"dist/esm/bin.mjs\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/gopd\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz\",\n \"integrity\": \"sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/graceful-fs\": {\n \"version\": \"4.2.11\",\n \"resolved\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz\",\n \"integrity\": \"sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/gray-matter\": {\n \"version\": \"4.0.3\",\n \"resolved\": \"https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz\",\n \"integrity\": \"sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"js-yaml\": \"^3.13.1\",\n \"kind-of\": \"^6.0.2\",\n \"section-matter\": \"^1.0.0\",\n \"strip-bom-string\": \"^1.0.0\"\n },\n \"engines\": {\n \"node\": \">=6.0\"\n }\n },\n \"node_modules/has-symbols\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz\",\n \"integrity\": \"sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/has-tostringtag\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz\",\n \"integrity\": \"sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"has-symbols\": \"^1.0.3\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/has-unicode\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz\",\n \"integrity\": \"sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/hasown\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz\",\n \"integrity\": \"sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"function-bind\": \"^1.1.2\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/hono\": {\n \"version\": \"4.11.7\",\n \"resolved\": \"https://registry.npmjs.org/hono/-/hono-4.11.7.tgz\",\n \"integrity\": \"sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"peer\": true,\n \"engines\": {\n \"node\": \">=16.9.0\"\n }\n },\n \"node_modules/http-errors\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz\",\n \"integrity\": \"sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"depd\": \"~2.0.0\",\n \"inherits\": \"~2.0.4\",\n \"setprototypeof\": \"~1.2.0\",\n \"statuses\": \"~2.0.2\",\n \"toidentifier\": \"~1.0.1\"\n },\n \"engines\": {\n \"node\": \">= 0.8\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/human-signals\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz\",\n \"integrity\": \"sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==\",\n \"dev\": true,\n \"license\": \"Apache-2.0\",\n \"engines\": {\n \"node\": \">=16.17.0\"\n }\n },\n \"node_modules/iconv-lite\": {\n \"version\": \"0.7.2\",\n \"resolved\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz\",\n \"integrity\": \"sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"safer-buffer\": \">= 2.1.2 < 3.0.0\"\n },\n \"engines\": {\n \"node\": \">=0.10.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/ignore\": {\n \"version\": \"7.0.5\",\n \"resolved\": \"https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz\",\n \"integrity\": \"sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 4\"\n }\n },\n \"node_modules/inherits\": {\n \"version\": \"2.0.4\",\n \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz\",\n \"integrity\": \"sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/ini\": {\n \"version\": \"1.3.8\",\n \"resolved\": \"https://registry.npmjs.org/ini/-/ini-1.3.8.tgz\",\n \"integrity\": \"sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/ipaddr.js\": {\n \"version\": \"1.9.1\",\n \"resolved\": \"https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz\",\n \"integrity\": \"sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.10\"\n }\n },\n \"node_modules/ipull\": {\n \"version\": \"3.9.3\",\n \"resolved\": \"https://registry.npmjs.org/ipull/-/ipull-3.9.3.tgz\",\n \"integrity\": \"sha512-ZMkxaopfwKHwmEuGDYx7giNBdLxbHbRCWcQVA1D2eqE4crUguupfxej6s7UqbidYEwT69dkyumYkY8DPHIxF9g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@tinyhttp/content-disposition\": \"^2.2.0\",\n \"async-retry\": \"^1.3.3\",\n \"chalk\": \"^5.3.0\",\n \"ci-info\": \"^4.0.0\",\n \"cli-spinners\": \"^2.9.2\",\n \"commander\": \"^10.0.0\",\n \"eventemitter3\": \"^5.0.1\",\n \"filenamify\": \"^6.0.0\",\n \"fs-extra\": \"^11.1.1\",\n \"is-unicode-supported\": \"^2.0.0\",\n \"lifecycle-utils\": \"^2.0.1\",\n \"lodash.debounce\": \"^4.0.8\",\n \"lowdb\": \"^7.0.1\",\n \"pretty-bytes\": \"^6.1.0\",\n \"pretty-ms\": \"^8.0.0\",\n \"sleep-promise\": \"^9.1.0\",\n \"slice-ansi\": \"^7.1.0\",\n \"stdout-update\": \"^4.0.1\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"bin\": {\n \"ipull\": \"dist/cli/cli.js\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/ido-pluto/ipull?sponsor=1\"\n },\n \"optionalDependencies\": {\n \"@reflink/reflink\": \"^0.1.16\"\n }\n },\n \"node_modules/ipull/node_modules/commander\": {\n \"version\": \"10.0.1\",\n \"resolved\": \"https://registry.npmjs.org/commander/-/commander-10.0.1.tgz\",\n \"integrity\": \"sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=14\"\n }\n },\n \"node_modules/ipull/node_modules/lifecycle-utils\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/lifecycle-utils/-/lifecycle-utils-2.1.0.tgz\",\n \"integrity\": \"sha512-AnrXnE2/OF9PHCyFg0RSqsnQTzV991XaZA/buhFDoc58xU7rhSCDgCz/09Lqpsn4MpoPHt7TRAXV1kWZypFVsA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/ipull/node_modules/parse-ms\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/parse-ms/-/parse-ms-3.0.0.tgz\",\n \"integrity\": \"sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ipull/node_modules/pretty-ms\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/pretty-ms/-/pretty-ms-8.0.0.tgz\",\n \"integrity\": \"sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"parse-ms\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">=14.16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/is-extendable\": {\n \"version\": \"0.1.1\",\n \"resolved\": \"https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz\",\n \"integrity\": \"sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/is-fullwidth-code-point\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz\",\n \"integrity\": \"sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/is-interactive\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz\",\n \"integrity\": \"sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/is-promise\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz\",\n \"integrity\": \"sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/is-stream\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz\",\n \"integrity\": \"sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/is-unicode-supported\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz\",\n \"integrity\": \"sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/isexe\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz\",\n \"integrity\": \"sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==\",\n \"license\": \"ISC\"\n },\n \"node_modules/jackspeak\": {\n \"version\": \"3.4.3\",\n \"resolved\": \"https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz\",\n \"integrity\": \"sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==\",\n \"license\": \"BlueOak-1.0.0\",\n \"dependencies\": {\n \"@isaacs/cliui\": \"^8.0.2\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n },\n \"optionalDependencies\": {\n \"@pkgjs/parseargs\": \"^0.11.0\"\n }\n },\n \"node_modules/jose\": {\n \"version\": \"6.1.3\",\n \"resolved\": \"https://registry.npmjs.org/jose/-/jose-6.1.3.tgz\",\n \"integrity\": \"sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"url\": \"https://github.com/sponsors/panva\"\n }\n },\n \"node_modules/joycon\": {\n \"version\": \"3.1.1\",\n \"resolved\": \"https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz\",\n \"integrity\": \"sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/js-tokens\": {\n \"version\": \"9.0.1\",\n \"resolved\": \"https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz\",\n \"integrity\": \"sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/js-yaml\": {\n \"version\": \"3.14.2\",\n \"resolved\": \"https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz\",\n \"integrity\": \"sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"argparse\": \"^1.0.7\",\n \"esprima\": \"^4.0.0\"\n },\n \"bin\": {\n \"js-yaml\": \"bin/js-yaml.js\"\n }\n },\n \"node_modules/json-schema-traverse\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz\",\n \"integrity\": \"sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/json-schema-typed\": {\n \"version\": \"8.0.2\",\n \"resolved\": \"https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz\",\n \"integrity\": \"sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==\",\n \"license\": \"BSD-2-Clause\",\n \"optional\": true\n },\n \"node_modules/jsonfile\": {\n \"version\": \"6.2.0\",\n \"resolved\": \"https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz\",\n \"integrity\": \"sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"universalify\": \"^2.0.0\"\n },\n \"optionalDependencies\": {\n \"graceful-fs\": \"^4.1.6\"\n }\n },\n \"node_modules/kareem\": {\n \"version\": \"2.6.3\",\n \"resolved\": \"https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz\",\n \"integrity\": \"sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==\",\n \"license\": \"Apache-2.0\",\n \"engines\": {\n \"node\": \">=12.0.0\"\n }\n },\n \"node_modules/kind-of\": {\n \"version\": \"6.0.3\",\n \"resolved\": \"https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz\",\n \"integrity\": \"sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/lifecycle-utils\": {\n \"version\": \"3.1.0\",\n \"resolved\": \"https://registry.npmjs.org/lifecycle-utils/-/lifecycle-utils-3.1.0.tgz\",\n \"integrity\": \"sha512-kVvegv+r/icjIo1dkHv1hznVQi4FzEVglJD2IU4w07HzevIyH3BAYsFZzEIbBk/nNZjXHGgclJ5g9rz9QdBCLw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/lilconfig\": {\n \"version\": \"3.1.3\",\n \"resolved\": \"https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz\",\n \"integrity\": \"sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=14\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/antonk52\"\n }\n },\n \"node_modules/lines-and-columns\": {\n \"version\": \"1.2.4\",\n \"resolved\": \"https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz\",\n \"integrity\": \"sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/load-tsconfig\": {\n \"version\": \"0.2.5\",\n \"resolved\": \"https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz\",\n \"integrity\": \"sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n }\n },\n \"node_modules/local-pkg\": {\n \"version\": \"0.5.1\",\n \"resolved\": \"https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz\",\n \"integrity\": \"sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"mlly\": \"^1.7.3\",\n \"pkg-types\": \"^1.2.1\"\n },\n \"engines\": {\n \"node\": \">=14\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/antfu\"\n }\n },\n \"node_modules/lodash.debounce\": {\n \"version\": \"4.0.8\",\n \"resolved\": \"https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz\",\n \"integrity\": \"sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/log-symbols\": {\n \"version\": \"7.0.1\",\n \"resolved\": \"https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz\",\n \"integrity\": \"sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"is-unicode-supported\": \"^2.0.0\",\n \"yoctocolors\": \"^2.1.1\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/loupe\": {\n \"version\": \"2.3.7\",\n \"resolved\": \"https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz\",\n \"integrity\": \"sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"get-func-name\": \"^2.0.1\"\n }\n },\n \"node_modules/lowdb\": {\n \"version\": \"7.0.1\",\n \"resolved\": \"https://registry.npmjs.org/lowdb/-/lowdb-7.0.1.tgz\",\n \"integrity\": \"sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"steno\": \"^4.0.2\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/typicode\"\n }\n },\n \"node_modules/lru-cache\": {\n \"version\": \"10.4.3\",\n \"resolved\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz\",\n \"integrity\": \"sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==\",\n \"license\": \"ISC\"\n },\n \"node_modules/magic-string\": {\n \"version\": \"0.30.21\",\n \"resolved\": \"https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz\",\n \"integrity\": \"sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jridgewell/sourcemap-codec\": \"^1.5.5\"\n }\n },\n \"node_modules/math-intrinsics\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz\",\n \"integrity\": \"sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/media-typer\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz\",\n \"integrity\": \"sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/memjs\": {\n \"version\": \"1.3.2\",\n \"resolved\": \"https://registry.npmjs.org/memjs/-/memjs-1.3.2.tgz\",\n \"integrity\": \"sha512-qUEg2g8vxPe+zPn09KidjIStHPtoBO8Cttm8bgJFWWabbsjQ9Av9Ky+6UcvKx6ue0LLb/LEhtcyQpRyKfzeXcg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/memory-pager\": {\n \"version\": \"1.5.0\",\n \"resolved\": \"https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz\",\n \"integrity\": \"sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==\",\n \"license\": \"MIT\"\n },\n \"node_modules/memory-stream\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz\",\n \"integrity\": \"sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"readable-stream\": \"^3.4.0\"\n }\n },\n \"node_modules/merge-descriptors\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz\",\n \"integrity\": \"sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/merge-stream\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz\",\n \"integrity\": \"sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/mime-db\": {\n \"version\": \"1.54.0\",\n \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz\",\n \"integrity\": \"sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/mime-types\": {\n \"version\": \"3.0.2\",\n \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz\",\n \"integrity\": \"sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"mime-db\": \"^1.54.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/mimic-fn\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz\",\n \"integrity\": \"sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/mimic-function\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz\",\n \"integrity\": \"sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/minimatch\": {\n \"version\": \"9.0.5\",\n \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz\",\n \"integrity\": \"sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"brace-expansion\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">=16 || 14 >=14.17\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/minimist\": {\n \"version\": \"1.2.8\",\n \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz\",\n \"integrity\": \"sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/minipass\": {\n \"version\": \"7.1.2\",\n \"resolved\": \"https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz\",\n \"integrity\": \"sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==\",\n \"license\": \"ISC\",\n \"engines\": {\n \"node\": \">=16 || 14 >=14.17\"\n }\n },\n \"node_modules/minizlib\": {\n \"version\": \"2.1.2\",\n \"resolved\": \"https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz\",\n \"integrity\": \"sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"minipass\": \"^3.0.0\",\n \"yallist\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">= 8\"\n }\n },\n \"node_modules/minizlib/node_modules/minipass\": {\n \"version\": \"3.3.6\",\n \"resolved\": \"https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz\",\n \"integrity\": \"sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"yallist\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/mkdirp\": {\n \"version\": \"1.0.4\",\n \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz\",\n \"integrity\": \"sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"bin\": {\n \"mkdirp\": \"bin/cmd.js\"\n },\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/mlly\": {\n \"version\": \"1.8.0\",\n \"resolved\": \"https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz\",\n \"integrity\": \"sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"acorn\": \"^8.15.0\",\n \"pathe\": \"^2.0.3\",\n \"pkg-types\": \"^1.3.1\",\n \"ufo\": \"^1.6.1\"\n }\n },\n \"node_modules/mongodb\": {\n \"version\": \"6.20.0\",\n \"resolved\": \"https://registry.npmjs.org/mongodb/-/mongodb-6.20.0.tgz\",\n \"integrity\": \"sha512-Tl6MEIU3K4Rq3TSHd+sZQqRBoGlFsOgNrH5ltAcFBV62Re3Fd+FcaVf8uSEQFOJ51SDowDVttBTONMfoYWrWlQ==\",\n \"license\": \"Apache-2.0\",\n \"dependencies\": {\n \"@mongodb-js/saslprep\": \"^1.3.0\",\n \"bson\": \"^6.10.4\",\n \"mongodb-connection-string-url\": \"^3.0.2\"\n },\n \"engines\": {\n \"node\": \">=16.20.1\"\n },\n \"peerDependencies\": {\n \"@aws-sdk/credential-providers\": \"^3.188.0\",\n \"@mongodb-js/zstd\": \"^1.1.0 || ^2.0.0\",\n \"gcp-metadata\": \"^5.2.0\",\n \"kerberos\": \"^2.0.1\",\n \"mongodb-client-encryption\": \">=6.0.0 <7\",\n \"snappy\": \"^7.3.2\",\n \"socks\": \"^2.7.1\"\n },\n \"peerDependenciesMeta\": {\n \"@aws-sdk/credential-providers\": {\n \"optional\": true\n },\n \"@mongodb-js/zstd\": {\n \"optional\": true\n },\n \"gcp-metadata\": {\n \"optional\": true\n },\n \"kerberos\": {\n \"optional\": true\n },\n \"mongodb-client-encryption\": {\n \"optional\": true\n },\n \"snappy\": {\n \"optional\": true\n },\n \"socks\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/mongodb-connection-string-url\": {\n \"version\": \"3.0.2\",\n \"resolved\": \"https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz\",\n \"integrity\": \"sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==\",\n \"license\": \"Apache-2.0\",\n \"dependencies\": {\n \"@types/whatwg-url\": \"^11.0.2\",\n \"whatwg-url\": \"^14.1.0 || ^13.0.0\"\n }\n },\n \"node_modules/mongoose\": {\n \"version\": \"8.22.0\",\n \"resolved\": \"https://registry.npmjs.org/mongoose/-/mongoose-8.22.0.tgz\",\n \"integrity\": \"sha512-LKTPPqD3CVcSZJRzPcwKiSVYTmAvBZeVT0V34vUiqPEo9sBmOEg1y4TpDbUb90Zf2lO4N05ailQnKxiapCN08g==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"bson\": \"^6.10.4\",\n \"kareem\": \"2.6.3\",\n \"mongodb\": \"~6.20.0\",\n \"mpath\": \"0.9.0\",\n \"mquery\": \"5.0.0\",\n \"ms\": \"2.1.3\",\n \"sift\": \"17.1.3\"\n },\n \"engines\": {\n \"node\": \">=16.20.1\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/mongoose\"\n }\n },\n \"node_modules/mpath\": {\n \"version\": \"0.9.0\",\n \"resolved\": \"https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz\",\n \"integrity\": \"sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=4.0.0\"\n }\n },\n \"node_modules/mquery\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz\",\n \"integrity\": \"sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"debug\": \"4.x\"\n },\n \"engines\": {\n \"node\": \">=14.0.0\"\n }\n },\n \"node_modules/ms\": {\n \"version\": \"2.1.3\",\n \"resolved\": \"https://registry.npmjs.org/ms/-/ms-2.1.3.tgz\",\n \"integrity\": \"sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==\",\n \"license\": \"MIT\"\n },\n \"node_modules/mz\": {\n \"version\": \"2.7.0\",\n \"resolved\": \"https://registry.npmjs.org/mz/-/mz-2.7.0.tgz\",\n \"integrity\": \"sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"any-promise\": \"^1.0.0\",\n \"object-assign\": \"^4.0.1\",\n \"thenify-all\": \"^1.0.0\"\n }\n },\n \"node_modules/nanoid\": {\n \"version\": \"3.3.11\",\n \"resolved\": \"https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz\",\n \"integrity\": \"sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==\",\n \"dev\": true,\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"bin\": {\n \"nanoid\": \"bin/nanoid.cjs\"\n },\n \"engines\": {\n \"node\": \"^10 || ^12 || ^13.7 || ^14 || >=15.0.1\"\n }\n },\n \"node_modules/natural\": {\n \"version\": \"6.12.0\",\n \"resolved\": \"https://registry.npmjs.org/natural/-/natural-6.12.0.tgz\",\n \"integrity\": \"sha512-ZV/cuaxOvJ7CSxQRYHc6nlx7ql6hVPQc20N5ubdqVbotWnnqsNc+0/QG+ACIC3XPQ4rfrQrdC/1k47v1cSszTQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"afinn-165\": \"^1.0.2\",\n \"afinn-165-financialmarketnews\": \"^3.0.0\",\n \"apparatus\": \"^0.0.10\",\n \"dotenv\": \"^16.4.5\",\n \"memjs\": \"^1.3.2\",\n \"mongoose\": \"^8.2.0\",\n \"pg\": \"^8.11.3\",\n \"redis\": \"^4.6.13\",\n \"safe-stable-stringify\": \"^2.2.0\",\n \"stopwords-iso\": \"^1.1.0\",\n \"sylvester\": \"^0.0.12\",\n \"underscore\": \"^1.9.1\",\n \"uuid\": \"^9.0.1\",\n \"wordnet-db\": \"^3.1.11\"\n },\n \"engines\": {\n \"node\": \">=0.4.10\"\n }\n },\n \"node_modules/negotiator\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz\",\n \"integrity\": \"sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/node-addon-api\": {\n \"version\": \"8.5.0\",\n \"resolved\": \"https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz\",\n \"integrity\": \"sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"^18 || ^20 || >= 21\"\n }\n },\n \"node_modules/node-api-headers\": {\n \"version\": \"1.8.0\",\n \"resolved\": \"https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.8.0.tgz\",\n \"integrity\": \"sha512-jfnmiKWjRAGbdD1yQS28bknFM1tbHC1oucyuMPjmkEs+kpiu76aRs40WlTmBmyEgzDM76ge1DQ7XJ3R5deiVjQ==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/node-llama-cpp\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/node-llama-cpp/-/node-llama-cpp-3.15.1.tgz\",\n \"integrity\": \"sha512-/fBNkuLGR2Q8xj2eeV12KXKZ9vCS2+o6aP11lW40pB9H6f0B3wOALi/liFrjhHukAoiH6C9wFTPzv6039+5DRA==\",\n \"hasInstallScript\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@huggingface/jinja\": \"^0.5.3\",\n \"async-retry\": \"^1.3.3\",\n \"bytes\": \"^3.1.2\",\n \"chalk\": \"^5.4.1\",\n \"chmodrp\": \"^1.0.2\",\n \"cmake-js\": \"^7.4.0\",\n \"cross-spawn\": \"^7.0.6\",\n \"env-var\": \"^7.5.0\",\n \"filenamify\": \"^6.0.0\",\n \"fs-extra\": \"^11.3.0\",\n \"ignore\": \"^7.0.4\",\n \"ipull\": \"^3.9.2\",\n \"is-unicode-supported\": \"^2.1.0\",\n \"lifecycle-utils\": \"^3.0.1\",\n \"log-symbols\": \"^7.0.0\",\n \"nanoid\": \"^5.1.5\",\n \"node-addon-api\": \"^8.3.1\",\n \"octokit\": \"^5.0.3\",\n \"ora\": \"^8.2.0\",\n \"pretty-ms\": \"^9.2.0\",\n \"proper-lockfile\": \"^4.1.2\",\n \"semver\": \"^7.7.1\",\n \"simple-git\": \"^3.27.0\",\n \"slice-ansi\": \"^7.1.0\",\n \"stdout-update\": \"^4.0.1\",\n \"strip-ansi\": \"^7.1.0\",\n \"validate-npm-package-name\": \"^6.0.0\",\n \"which\": \"^5.0.0\",\n \"yargs\": \"^17.7.2\"\n },\n \"bin\": {\n \"nlc\": \"dist/cli/cli.js\",\n \"node-llama-cpp\": \"dist/cli/cli.js\"\n },\n \"engines\": {\n \"node\": \">=20.0.0\"\n },\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/giladgd\"\n },\n \"optionalDependencies\": {\n \"@node-llama-cpp/linux-arm64\": \"3.15.1\",\n \"@node-llama-cpp/linux-armv7l\": \"3.15.1\",\n \"@node-llama-cpp/linux-x64\": \"3.15.1\",\n \"@node-llama-cpp/linux-x64-cuda\": \"3.15.1\",\n \"@node-llama-cpp/linux-x64-cuda-ext\": \"3.15.1\",\n \"@node-llama-cpp/linux-x64-vulkan\": \"3.15.1\",\n \"@node-llama-cpp/mac-arm64-metal\": \"3.15.1\",\n \"@node-llama-cpp/mac-x64\": \"3.15.1\",\n \"@node-llama-cpp/win-arm64\": \"3.15.1\",\n \"@node-llama-cpp/win-x64\": \"3.15.1\",\n \"@node-llama-cpp/win-x64-cuda\": \"3.15.1\",\n \"@node-llama-cpp/win-x64-cuda-ext\": \"3.15.1\",\n \"@node-llama-cpp/win-x64-vulkan\": \"3.15.1\"\n },\n \"peerDependencies\": {\n \"typescript\": \">=5.0.0\"\n },\n \"peerDependenciesMeta\": {\n \"typescript\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/node-llama-cpp/node_modules/isexe\": {\n \"version\": \"3.1.1\",\n \"resolved\": \"https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz\",\n \"integrity\": \"sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=16\"\n }\n },\n \"node_modules/node-llama-cpp/node_modules/nanoid\": {\n \"version\": \"5.1.6\",\n \"resolved\": \"https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz\",\n \"integrity\": \"sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"bin\": {\n \"nanoid\": \"bin/nanoid.js\"\n },\n \"engines\": {\n \"node\": \"^18 || >=20\"\n }\n },\n \"node_modules/node-llama-cpp/node_modules/which\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/which/-/which-5.0.0.tgz\",\n \"integrity\": \"sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"isexe\": \"^3.1.1\"\n },\n \"bin\": {\n \"node-which\": \"bin/which.js\"\n },\n \"engines\": {\n \"node\": \"^18.17.0 || >=20.5.0\"\n }\n },\n \"node_modules/npm-run-path\": {\n \"version\": \"5.3.0\",\n \"resolved\": \"https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz\",\n \"integrity\": \"sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"path-key\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/npm-run-path/node_modules/path-key\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz\",\n \"integrity\": \"sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/npmlog\": {\n \"version\": \"6.0.2\",\n \"resolved\": \"https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz\",\n \"integrity\": \"sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==\",\n \"deprecated\": \"This package is no longer supported.\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"are-we-there-yet\": \"^3.0.0\",\n \"console-control-strings\": \"^1.1.0\",\n \"gauge\": \"^4.0.3\",\n \"set-blocking\": \"^2.0.0\"\n },\n \"engines\": {\n \"node\": \"^12.13.0 || ^14.15.0 || >=16.0.0\"\n }\n },\n \"node_modules/object-assign\": {\n \"version\": \"4.1.1\",\n \"resolved\": \"https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz\",\n \"integrity\": \"sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==\",\n \"devOptional\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/object-inspect\": {\n \"version\": \"1.13.4\",\n \"resolved\": \"https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz\",\n \"integrity\": \"sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/octokit\": {\n \"version\": \"5.0.5\",\n \"resolved\": \"https://registry.npmjs.org/octokit/-/octokit-5.0.5.tgz\",\n \"integrity\": \"sha512-4+/OFSqOjoyULo7eN7EA97DE0Xydj/PW5aIckxqQIoFjFwqXKuFCvXUJObyJfBF9Khu4RL/jlDRI9FPaMGfPnw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/app\": \"^16.1.2\",\n \"@octokit/core\": \"^7.0.6\",\n \"@octokit/oauth-app\": \"^8.0.3\",\n \"@octokit/plugin-paginate-graphql\": \"^6.0.0\",\n \"@octokit/plugin-paginate-rest\": \"^14.0.0\",\n \"@octokit/plugin-rest-endpoint-methods\": \"^17.0.0\",\n \"@octokit/plugin-retry\": \"^8.0.3\",\n \"@octokit/plugin-throttling\": \"^11.0.3\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"@octokit/webhooks\": \"^14.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/on-finished\": {\n \"version\": \"2.4.1\",\n \"resolved\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz\",\n \"integrity\": \"sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ee-first\": \"1.1.1\"\n },\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/once\": {\n \"version\": \"1.4.0\",\n \"resolved\": \"https://registry.npmjs.org/once/-/once-1.4.0.tgz\",\n \"integrity\": \"sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"wrappy\": \"1\"\n }\n },\n \"node_modules/onetime\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz\",\n \"integrity\": \"sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"mimic-fn\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ora\": {\n \"version\": \"8.2.0\",\n \"resolved\": \"https://registry.npmjs.org/ora/-/ora-8.2.0.tgz\",\n \"integrity\": \"sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"chalk\": \"^5.3.0\",\n \"cli-cursor\": \"^5.0.0\",\n \"cli-spinners\": \"^2.9.2\",\n \"is-interactive\": \"^2.0.0\",\n \"is-unicode-supported\": \"^2.0.0\",\n \"log-symbols\": \"^6.0.0\",\n \"stdin-discarder\": \"^0.2.2\",\n \"string-width\": \"^7.2.0\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ora/node_modules/emoji-regex\": {\n \"version\": \"10.6.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz\",\n \"integrity\": \"sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/ora/node_modules/log-symbols\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz\",\n \"integrity\": \"sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"chalk\": \"^5.3.0\",\n \"is-unicode-supported\": \"^1.3.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz\",\n \"integrity\": \"sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ora/node_modules/string-width\": {\n \"version\": \"7.2.0\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz\",\n \"integrity\": \"sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^10.3.0\",\n \"get-east-asian-width\": \"^1.0.0\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/p-limit\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz\",\n \"integrity\": \"sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"yocto-queue\": \"^1.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/package-json-from-dist\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz\",\n \"integrity\": \"sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==\",\n \"license\": \"BlueOak-1.0.0\"\n },\n \"node_modules/parse-ms\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz\",\n \"integrity\": \"sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/parseurl\": {\n \"version\": \"1.3.3\",\n \"resolved\": \"https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz\",\n \"integrity\": \"sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/path-key\": {\n \"version\": \"3.1.1\",\n \"resolved\": \"https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz\",\n \"integrity\": \"sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/path-scurry\": {\n \"version\": \"1.11.1\",\n \"resolved\": \"https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz\",\n \"integrity\": \"sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==\",\n \"license\": \"BlueOak-1.0.0\",\n \"dependencies\": {\n \"lru-cache\": \"^10.2.0\",\n \"minipass\": \"^5.0.0 || ^6.0.2 || ^7.0.0\"\n },\n \"engines\": {\n \"node\": \">=16 || 14 >=14.18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/path-to-regexp\": {\n \"version\": \"8.3.0\",\n \"resolved\": \"https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz\",\n \"integrity\": \"sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/pathe\": {\n \"version\": \"2.0.3\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz\",\n \"integrity\": \"sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/pathval\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz\",\n \"integrity\": \"sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"*\"\n }\n },\n \"node_modules/pg\": {\n \"version\": \"8.17.2\",\n \"resolved\": \"https://registry.npmjs.org/pg/-/pg-8.17.2.tgz\",\n \"integrity\": \"sha512-vjbKdiBJRqzcYw1fNU5KuHyYvdJ1qpcQg1CeBrHFqV1pWgHeVR6j/+kX0E1AAXfyuLUGY1ICrN2ELKA/z2HWzw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"pg-connection-string\": \"^2.10.1\",\n \"pg-pool\": \"^3.11.0\",\n \"pg-protocol\": \"^1.11.0\",\n \"pg-types\": \"2.2.0\",\n \"pgpass\": \"1.0.5\"\n },\n \"engines\": {\n \"node\": \">= 16.0.0\"\n },\n \"optionalDependencies\": {\n \"pg-cloudflare\": \"^1.3.0\"\n },\n \"peerDependencies\": {\n \"pg-native\": \">=3.0.1\"\n },\n \"peerDependenciesMeta\": {\n \"pg-native\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/pg-cloudflare\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz\",\n \"integrity\": \"sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/pg-connection-string\": {\n \"version\": \"2.10.1\",\n \"resolved\": \"https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.10.1.tgz\",\n \"integrity\": \"sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw==\",\n \"license\": \"MIT\"\n },\n \"node_modules/pg-int8\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz\",\n \"integrity\": \"sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==\",\n \"license\": \"ISC\",\n \"engines\": {\n \"node\": \">=4.0.0\"\n }\n },\n \"node_modules/pg-pool\": {\n \"version\": \"3.11.0\",\n \"resolved\": \"https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz\",\n \"integrity\": \"sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"pg\": \">=8.0\"\n }\n },\n \"node_modules/pg-protocol\": {\n \"version\": \"1.11.0\",\n \"resolved\": \"https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz\",\n \"integrity\": \"sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==\",\n \"license\": \"MIT\"\n },\n \"node_modules/pg-types\": {\n \"version\": \"2.2.0\",\n \"resolved\": \"https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz\",\n \"integrity\": \"sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"pg-int8\": \"1.0.1\",\n \"postgres-array\": \"~2.0.0\",\n \"postgres-bytea\": \"~1.0.0\",\n \"postgres-date\": \"~1.0.4\",\n \"postgres-interval\": \"^1.1.0\"\n },\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/pgpass\": {\n \"version\": \"1.0.5\",\n \"resolved\": \"https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz\",\n \"integrity\": \"sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"split2\": \"^4.1.0\"\n }\n },\n \"node_modules/picocolors\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz\",\n \"integrity\": \"sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==\",\n \"dev\": true,\n \"license\": \"ISC\"\n },\n \"node_modules/picomatch\": {\n \"version\": \"4.0.3\",\n \"resolved\": \"https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz\",\n \"integrity\": \"sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/jonschlinkert\"\n }\n },\n \"node_modules/pirates\": {\n \"version\": \"4.0.7\",\n \"resolved\": \"https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz\",\n \"integrity\": \"sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">= 6\"\n }\n },\n \"node_modules/pkce-challenge\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz\",\n \"integrity\": \"sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=16.20.0\"\n }\n },\n \"node_modules/pkg-types\": {\n \"version\": \"1.3.1\",\n \"resolved\": \"https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz\",\n \"integrity\": \"sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"confbox\": \"^0.1.8\",\n \"mlly\": \"^1.7.4\",\n \"pathe\": \"^2.0.1\"\n }\n },\n \"node_modules/postcss\": {\n \"version\": \"8.5.6\",\n \"resolved\": \"https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz\",\n \"integrity\": \"sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==\",\n \"dev\": true,\n \"funding\": [\n {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/postcss/\"\n },\n {\n \"type\": \"tidelift\",\n \"url\": \"https://tidelift.com/funding/github/npm/postcss\"\n },\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"dependencies\": {\n \"nanoid\": \"^3.3.11\",\n \"picocolors\": \"^1.1.1\",\n \"source-map-js\": \"^1.2.1\"\n },\n \"engines\": {\n \"node\": \"^10 || ^12 || >=14\"\n }\n },\n \"node_modules/postcss-load-config\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz\",\n \"integrity\": \"sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==\",\n \"dev\": true,\n \"funding\": [\n {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/postcss/\"\n },\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"dependencies\": {\n \"lilconfig\": \"^3.1.1\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n },\n \"peerDependencies\": {\n \"jiti\": \">=1.21.0\",\n \"postcss\": \">=8.0.9\",\n \"tsx\": \"^4.8.1\",\n \"yaml\": \"^2.4.2\"\n },\n \"peerDependenciesMeta\": {\n \"jiti\": {\n \"optional\": true\n },\n \"postcss\": {\n \"optional\": true\n },\n \"tsx\": {\n \"optional\": true\n },\n \"yaml\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/postgres-array\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz\",\n \"integrity\": \"sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/postgres-bytea\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz\",\n \"integrity\": \"sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/postgres-date\": {\n \"version\": \"1.0.7\",\n \"resolved\": \"https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz\",\n \"integrity\": \"sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/postgres-interval\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz\",\n \"integrity\": \"sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"xtend\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/pretty-bytes\": {\n \"version\": \"6.1.1\",\n \"resolved\": \"https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz\",\n \"integrity\": \"sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"^14.13.1 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/pretty-format\": {\n \"version\": \"29.7.0\",\n \"resolved\": \"https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz\",\n \"integrity\": \"sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jest/schemas\": \"^29.6.3\",\n \"ansi-styles\": \"^5.0.0\",\n \"react-is\": \"^18.0.0\"\n },\n \"engines\": {\n \"node\": \"^14.15.0 || ^16.10.0 || >=18.0.0\"\n }\n },\n \"node_modules/pretty-ms\": {\n \"version\": \"9.3.0\",\n \"resolved\": \"https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz\",\n \"integrity\": \"sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"parse-ms\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/proper-lockfile\": {\n \"version\": \"4.1.2\",\n \"resolved\": \"https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz\",\n \"integrity\": \"sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"graceful-fs\": \"^4.2.4\",\n \"retry\": \"^0.12.0\",\n \"signal-exit\": \"^3.0.2\"\n }\n },\n \"node_modules/proper-lockfile/node_modules/retry\": {\n \"version\": \"0.12.0\",\n \"resolved\": \"https://registry.npmjs.org/retry/-/retry-0.12.0.tgz\",\n \"integrity\": \"sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 4\"\n }\n },\n \"node_modules/proper-lockfile/node_modules/signal-exit\": {\n \"version\": \"3.0.7\",\n \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz\",\n \"integrity\": \"sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/proxy-addr\": {\n \"version\": \"2.0.7\",\n \"resolved\": \"https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz\",\n \"integrity\": \"sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"forwarded\": \"0.2.0\",\n \"ipaddr.js\": \"1.9.1\"\n },\n \"engines\": {\n \"node\": \">= 0.10\"\n }\n },\n \"node_modules/proxy-from-env\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz\",\n \"integrity\": \"sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/punycode\": {\n \"version\": \"2.3.1\",\n \"resolved\": \"https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz\",\n \"integrity\": \"sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=6\"\n }\n },\n \"node_modules/qmd\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"git+ssh://git@github.com/tobi/qmd.git#63028fd5e905f653bbb3f55e1857b48efba6ba6d\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.25.1\",\n \"node-llama-cpp\": \"^3.14.5\",\n \"sqlite-vec\": \"^0.1.7-alpha.2\",\n \"yaml\": \"^2.8.2\",\n \"zod\": \"^4.2.1\"\n },\n \"bin\": {\n \"qmd\": \"qmd\"\n },\n \"engines\": {\n \"bun\": \">=1.0.0\"\n },\n \"optionalDependencies\": {\n \"sqlite-vec-darwin-arm64\": \"^0.1.7-alpha.2\",\n \"sqlite-vec-darwin-x64\": \"^0.1.7-alpha.2\",\n \"sqlite-vec-linux-x64\": \"^0.1.7-alpha.2\",\n \"sqlite-vec-win32-x64\": \"^0.1.7-alpha.2\"\n },\n \"peerDependencies\": {\n \"typescript\": \"^5.9.3\"\n }\n },\n \"node_modules/qmd/node_modules/sqlite-vec-win32-x64\": {\n \"optional\": true\n },\n \"node_modules/qs\": {\n \"version\": \"6.14.1\",\n \"resolved\": \"https://registry.npmjs.org/qs/-/qs-6.14.1.tgz\",\n \"integrity\": \"sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==\",\n \"license\": \"BSD-3-Clause\",\n \"optional\": true,\n \"dependencies\": {\n \"side-channel\": \"^1.1.0\"\n },\n \"engines\": {\n \"node\": \">=0.6\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/range-parser\": {\n \"version\": \"1.2.1\",\n \"resolved\": \"https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz\",\n \"integrity\": \"sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/raw-body\": {\n \"version\": \"3.0.2\",\n \"resolved\": \"https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz\",\n \"integrity\": \"sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"bytes\": \"~3.1.2\",\n \"http-errors\": \"~2.0.1\",\n \"iconv-lite\": \"~0.7.0\",\n \"unpipe\": \"~1.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.10\"\n }\n },\n \"node_modules/rc\": {\n \"version\": \"1.2.8\",\n \"resolved\": \"https://registry.npmjs.org/rc/-/rc-1.2.8.tgz\",\n \"integrity\": \"sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==\",\n \"license\": \"(BSD-2-Clause OR MIT OR Apache-2.0)\",\n \"optional\": true,\n \"dependencies\": {\n \"deep-extend\": \"^0.6.0\",\n \"ini\": \"~1.3.0\",\n \"minimist\": \"^1.2.0\",\n \"strip-json-comments\": \"~2.0.1\"\n },\n \"bin\": {\n \"rc\": \"cli.js\"\n }\n },\n \"node_modules/react-is\": {\n \"version\": \"18.3.1\",\n \"resolved\": \"https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz\",\n \"integrity\": \"sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/readable-stream\": {\n \"version\": \"3.6.2\",\n \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz\",\n \"integrity\": \"sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"inherits\": \"^2.0.3\",\n \"string_decoder\": \"^1.1.1\",\n \"util-deprecate\": \"^1.0.1\"\n },\n \"engines\": {\n \"node\": \">= 6\"\n }\n },\n \"node_modules/readdirp\": {\n \"version\": \"4.1.2\",\n \"resolved\": \"https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz\",\n \"integrity\": \"sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">= 14.18.0\"\n },\n \"funding\": {\n \"type\": \"individual\",\n \"url\": \"https://paulmillr.com/funding/\"\n }\n },\n \"node_modules/redis\": {\n \"version\": \"4.7.1\",\n \"resolved\": \"https://registry.npmjs.org/redis/-/redis-4.7.1.tgz\",\n \"integrity\": \"sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==\",\n \"license\": \"MIT\",\n \"workspaces\": [\n \"./packages/*\"\n ],\n \"dependencies\": {\n \"@redis/bloom\": \"1.2.0\",\n \"@redis/client\": \"1.6.1\",\n \"@redis/graph\": \"1.1.1\",\n \"@redis/json\": \"1.0.7\",\n \"@redis/search\": \"1.2.0\",\n \"@redis/time-series\": \"1.1.0\"\n }\n },\n \"node_modules/require-directory\": {\n \"version\": \"2.1.1\",\n \"resolved\": \"https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz\",\n \"integrity\": \"sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/require-from-string\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz\",\n \"integrity\": \"sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/resolve-from\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz\",\n \"integrity\": \"sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/restore-cursor\": {\n \"version\": \"5.1.0\",\n \"resolved\": \"https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz\",\n \"integrity\": \"sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"onetime\": \"^7.0.0\",\n \"signal-exit\": \"^4.1.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/restore-cursor/node_modules/onetime\": {\n \"version\": \"7.0.0\",\n \"resolved\": \"https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz\",\n \"integrity\": \"sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"mimic-function\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/retry\": {\n \"version\": \"0.13.1\",\n \"resolved\": \"https://registry.npmjs.org/retry/-/retry-0.13.1.tgz\",\n \"integrity\": \"sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 4\"\n }\n },\n \"node_modules/rollup\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz\",\n \"integrity\": \"sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@types/estree\": \"1.0.8\"\n },\n \"bin\": {\n \"rollup\": \"dist/bin/rollup\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\",\n \"npm\": \">=8.0.0\"\n },\n \"optionalDependencies\": {\n \"@rollup/rollup-android-arm-eabi\": \"4.57.1\",\n \"@rollup/rollup-android-arm64\": \"4.57.1\",\n \"@rollup/rollup-darwin-arm64\": \"4.57.1\",\n \"@rollup/rollup-darwin-x64\": \"4.57.1\",\n \"@rollup/rollup-freebsd-arm64\": \"4.57.1\",\n \"@rollup/rollup-freebsd-x64\": \"4.57.1\",\n \"@rollup/rollup-linux-arm-gnueabihf\": \"4.57.1\",\n \"@rollup/rollup-linux-arm-musleabihf\": \"4.57.1\",\n \"@rollup/rollup-linux-arm64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-arm64-musl\": \"4.57.1\",\n \"@rollup/rollup-linux-loong64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-loong64-musl\": \"4.57.1\",\n \"@rollup/rollup-linux-ppc64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-ppc64-musl\": \"4.57.1\",\n \"@rollup/rollup-linux-riscv64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-riscv64-musl\": \"4.57.1\",\n \"@rollup/rollup-linux-s390x-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-x64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-x64-musl\": \"4.57.1\",\n \"@rollup/rollup-openbsd-x64\": \"4.57.1\",\n \"@rollup/rollup-openharmony-arm64\": \"4.57.1\",\n \"@rollup/rollup-win32-arm64-msvc\": \"4.57.1\",\n \"@rollup/rollup-win32-ia32-msvc\": \"4.57.1\",\n \"@rollup/rollup-win32-x64-gnu\": \"4.57.1\",\n \"@rollup/rollup-win32-x64-msvc\": \"4.57.1\",\n \"fsevents\": \"~2.3.2\"\n }\n },\n \"node_modules/router\": {\n \"version\": \"2.2.0\",\n \"resolved\": \"https://registry.npmjs.org/router/-/router-2.2.0.tgz\",\n \"integrity\": \"sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"debug\": \"^4.4.0\",\n \"depd\": \"^2.0.0\",\n \"is-promise\": \"^4.0.0\",\n \"parseurl\": \"^1.3.3\",\n \"path-to-regexp\": \"^8.0.0\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n }\n },\n \"node_modules/safe-buffer\": {\n \"version\": \"5.2.1\",\n \"resolved\": \"https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz\",\n \"integrity\": \"sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/feross\"\n },\n {\n \"type\": \"patreon\",\n \"url\": \"https://www.patreon.com/feross\"\n },\n {\n \"type\": \"consulting\",\n \"url\": \"https://feross.org/support\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/safe-stable-stringify\": {\n \"version\": \"2.5.0\",\n \"resolved\": \"https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz\",\n \"integrity\": \"sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/safer-buffer\": {\n \"version\": \"2.1.2\",\n \"resolved\": \"https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz\",\n \"integrity\": \"sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/section-matter\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz\",\n \"integrity\": \"sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"extend-shallow\": \"^2.0.1\",\n \"kind-of\": \"^6.0.0\"\n },\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/semver\": {\n \"version\": \"7.7.3\",\n \"resolved\": \"https://registry.npmjs.org/semver/-/semver-7.7.3.tgz\",\n \"integrity\": \"sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"bin\": {\n \"semver\": \"bin/semver.js\"\n },\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/send\": {\n \"version\": \"1.2.1\",\n \"resolved\": \"https://registry.npmjs.org/send/-/send-1.2.1.tgz\",\n \"integrity\": \"sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"debug\": \"^4.4.3\",\n \"encodeurl\": \"^2.0.0\",\n \"escape-html\": \"^1.0.3\",\n \"etag\": \"^1.8.1\",\n \"fresh\": \"^2.0.0\",\n \"http-errors\": \"^2.0.1\",\n \"mime-types\": \"^3.0.2\",\n \"ms\": \"^2.1.3\",\n \"on-finished\": \"^2.4.1\",\n \"range-parser\": \"^1.2.1\",\n \"statuses\": \"^2.0.2\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/serve-static\": {\n \"version\": \"2.2.1\",\n \"resolved\": \"https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz\",\n \"integrity\": \"sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"encodeurl\": \"^2.0.0\",\n \"escape-html\": \"^1.0.3\",\n \"parseurl\": \"^1.3.3\",\n \"send\": \"^1.2.0\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/set-blocking\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz\",\n \"integrity\": \"sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/setprototypeof\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz\",\n \"integrity\": \"sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/shebang-command\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz\",\n \"integrity\": \"sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"shebang-regex\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/shebang-regex\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz\",\n \"integrity\": \"sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/side-channel\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz\",\n \"integrity\": \"sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\",\n \"object-inspect\": \"^1.13.3\",\n \"side-channel-list\": \"^1.0.0\",\n \"side-channel-map\": \"^1.0.1\",\n \"side-channel-weakmap\": \"^1.0.2\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/side-channel-list\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz\",\n \"integrity\": \"sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\",\n \"object-inspect\": \"^1.13.3\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/side-channel-map\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz\",\n \"integrity\": \"sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bound\": \"^1.0.2\",\n \"es-errors\": \"^1.3.0\",\n \"get-intrinsic\": \"^1.2.5\",\n \"object-inspect\": \"^1.13.3\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/side-channel-weakmap\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz\",\n \"integrity\": \"sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bound\": \"^1.0.2\",\n \"es-errors\": \"^1.3.0\",\n \"get-intrinsic\": \"^1.2.5\",\n \"object-inspect\": \"^1.13.3\",\n \"side-channel-map\": \"^1.0.1\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/sift\": {\n \"version\": \"17.1.3\",\n \"resolved\": \"https://registry.npmjs.org/sift/-/sift-17.1.3.tgz\",\n \"integrity\": \"sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==\",\n \"license\": \"MIT\"\n },\n \"node_modules/siginfo\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz\",\n \"integrity\": \"sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==\",\n \"dev\": true,\n \"license\": \"ISC\"\n },\n \"node_modules/signal-exit\": {\n \"version\": \"4.1.0\",\n \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz\",\n \"integrity\": \"sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==\",\n \"license\": \"ISC\",\n \"engines\": {\n \"node\": \">=14\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/simple-git\": {\n \"version\": \"3.30.0\",\n \"resolved\": \"https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz\",\n \"integrity\": \"sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@kwsites/file-exists\": \"^1.1.1\",\n \"@kwsites/promise-deferred\": \"^1.1.1\",\n \"debug\": \"^4.4.0\"\n },\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/steveukx/git-js?sponsor=1\"\n }\n },\n \"node_modules/sleep-promise\": {\n \"version\": \"9.1.0\",\n \"resolved\": \"https://registry.npmjs.org/sleep-promise/-/sleep-promise-9.1.0.tgz\",\n \"integrity\": \"sha512-UHYzVpz9Xn8b+jikYSD6bqvf754xL2uBUzDFwiU6NcdZeifPr6UfgU43xpkPu67VMS88+TI2PSI7Eohgqf2fKA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/slice-ansi\": {\n \"version\": \"7.1.2\",\n \"resolved\": \"https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz\",\n \"integrity\": \"sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-styles\": \"^6.2.1\",\n \"is-fullwidth-code-point\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/slice-ansi?sponsor=1\"\n }\n },\n \"node_modules/slice-ansi/node_modules/ansi-styles\": {\n \"version\": \"6.2.3\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz\",\n \"integrity\": \"sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/slice-ansi/node_modules/is-fullwidth-code-point\": {\n \"version\": \"5.1.0\",\n \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz\",\n \"integrity\": \"sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"get-east-asian-width\": \"^1.3.1\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/source-map\": {\n \"version\": \"0.7.6\",\n \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz\",\n \"integrity\": \"sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==\",\n \"dev\": true,\n \"license\": \"BSD-3-Clause\",\n \"engines\": {\n \"node\": \">= 12\"\n }\n },\n \"node_modules/source-map-js\": {\n \"version\": \"1.2.1\",\n \"resolved\": \"https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz\",\n \"integrity\": \"sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==\",\n \"dev\": true,\n \"license\": \"BSD-3-Clause\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/sparse-bitfield\": {\n \"version\": \"3.0.3\",\n \"resolved\": \"https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz\",\n \"integrity\": \"sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"memory-pager\": \"^1.0.2\"\n }\n },\n \"node_modules/split2\": {\n \"version\": \"4.2.0\",\n \"resolved\": \"https://registry.npmjs.org/split2/-/split2-4.2.0.tgz\",\n \"integrity\": \"sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==\",\n \"license\": \"ISC\",\n \"engines\": {\n \"node\": \">= 10.x\"\n }\n },\n \"node_modules/sprintf-js\": {\n \"version\": \"1.0.3\",\n \"resolved\": \"https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz\",\n \"integrity\": \"sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==\",\n \"license\": \"BSD-3-Clause\"\n },\n \"node_modules/sqlite-vec\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec/-/sqlite-vec-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-rNgRCv+4V4Ed3yc33Qr+nNmjhtrMnnHzXfLVPeGb28Dx5mmDL3Ngw/Wk8vhCGjj76+oC6gnkmMG8y73BZWGBwQ==\",\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"optionalDependencies\": {\n \"sqlite-vec-darwin-arm64\": \"0.1.7-alpha.2\",\n \"sqlite-vec-darwin-x64\": \"0.1.7-alpha.2\",\n \"sqlite-vec-linux-arm64\": \"0.1.7-alpha.2\",\n \"sqlite-vec-linux-x64\": \"0.1.7-alpha.2\",\n \"sqlite-vec-windows-x64\": \"0.1.7-alpha.2\"\n }\n },\n \"node_modules/sqlite-vec-darwin-arm64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-darwin-arm64/-/sqlite-vec-darwin-arm64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-raIATOqFYkeCHhb/t3r7W7Cf2lVYdf4J3ogJ6GFc8PQEgHCPEsi+bYnm2JT84MzLfTlSTIdxr4/NKv+zF7oLPw==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ]\n },\n \"node_modules/sqlite-vec-darwin-x64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-darwin-x64/-/sqlite-vec-darwin-x64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-jeZEELsQjjRsVojsvU5iKxOvkaVuE+JYC8Y4Ma8U45aAERrDYmqZoHvgSG7cg1PXL3bMlumFTAmHynf1y4pOzA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ]\n },\n \"node_modules/sqlite-vec-linux-arm64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-linux-arm64/-/sqlite-vec-linux-arm64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-6Spj4Nfi7tG13jsUG+W7jnT0bCTWbyPImu2M8nWp20fNrd1SZ4g3CSlDAK8GBdavX7wRlbBHCZ+BDa++rbDewA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/sqlite-vec-linux-x64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-linux-x64/-/sqlite-vec-linux-x64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-IcgrbHaDccTVhXDf8Orwdc2+hgDLAFORl6OBUhcvlmwswwBP1hqBTSEhovClG4NItwTOBNgpwOoQ7Qp3VDPWLg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/sqlite-vec-windows-x64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-windows-x64/-/sqlite-vec-windows-x64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-TRP6hTjAcwvQ6xpCZvjP00pdlda8J38ArFy1lMYhtQWXiIBmWnhMaMbq4kaeCYwvTTddfidatRS+TJrwIKB/oQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/stackback\": {\n \"version\": \"0.0.2\",\n \"resolved\": \"https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz\",\n \"integrity\": \"sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/statuses\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz\",\n \"integrity\": \"sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/std-env\": {\n \"version\": \"3.10.0\",\n \"resolved\": \"https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz\",\n \"integrity\": \"sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/stdin-discarder\": {\n \"version\": \"0.2.2\",\n \"resolved\": \"https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz\",\n \"integrity\": \"sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/stdout-update\": {\n \"version\": \"4.0.1\",\n \"resolved\": \"https://registry.npmjs.org/stdout-update/-/stdout-update-4.0.1.tgz\",\n \"integrity\": \"sha512-wiS21Jthlvl1to+oorePvcyrIkiG/6M3D3VTmDUlJm7Cy6SbFhKkAvX+YBuHLxck/tO3mrdpC/cNesigQc3+UQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-escapes\": \"^6.2.0\",\n \"ansi-styles\": \"^6.2.1\",\n \"string-width\": \"^7.1.0\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"engines\": {\n \"node\": \">=16.0.0\"\n }\n },\n \"node_modules/stdout-update/node_modules/ansi-styles\": {\n \"version\": \"6.2.3\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz\",\n \"integrity\": \"sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/stdout-update/node_modules/emoji-regex\": {\n \"version\": \"10.6.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz\",\n \"integrity\": \"sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/stdout-update/node_modules/string-width\": {\n \"version\": \"7.2.0\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz\",\n \"integrity\": \"sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^10.3.0\",\n \"get-east-asian-width\": \"^1.0.0\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/steno\": {\n \"version\": \"4.0.2\",\n \"resolved\": \"https://registry.npmjs.org/steno/-/steno-4.0.2.tgz\",\n \"integrity\": \"sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/typicode\"\n }\n },\n \"node_modules/stopwords-iso\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/stopwords-iso/-/stopwords-iso-1.1.0.tgz\",\n \"integrity\": \"sha512-I6GPS/E0zyieHehMRPQcqkiBMJKGgLta+1hREixhoLPqEA0AlVFiC43dl8uPpmkkeRdDMzYRWFWk5/l9x7nmNg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/string_decoder\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz\",\n \"integrity\": \"sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"safe-buffer\": \"~5.2.0\"\n }\n },\n \"node_modules/string-width\": {\n \"version\": \"5.1.2\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz\",\n \"integrity\": \"sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"eastasianwidth\": \"^0.2.0\",\n \"emoji-regex\": \"^9.2.2\",\n \"strip-ansi\": \"^7.0.1\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/string-width-cjs\": {\n \"name\": \"string-width\",\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/string-width-cjs/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/string-width-cjs/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\"\n },\n \"node_modules/string-width-cjs/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/strip-ansi\": {\n \"version\": \"7.1.2\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz\",\n \"integrity\": \"sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-regex\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/strip-ansi?sponsor=1\"\n }\n },\n \"node_modules/strip-ansi-cjs\": {\n \"name\": \"strip-ansi\",\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/strip-ansi-cjs/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/strip-bom-string\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz\",\n \"integrity\": \"sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/strip-final-newline\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz\",\n \"integrity\": \"sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/strip-json-comments\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz\",\n \"integrity\": \"sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/strip-literal\": {\n \"version\": \"2.1.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz\",\n \"integrity\": \"sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"js-tokens\": \"^9.0.1\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/antfu\"\n }\n },\n \"node_modules/sucrase\": {\n \"version\": \"3.35.1\",\n \"resolved\": \"https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz\",\n \"integrity\": \"sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jridgewell/gen-mapping\": \"^0.3.2\",\n \"commander\": \"^4.0.0\",\n \"lines-and-columns\": \"^1.1.6\",\n \"mz\": \"^2.7.0\",\n \"pirates\": \"^4.0.1\",\n \"tinyglobby\": \"^0.2.11\",\n \"ts-interface-checker\": \"^0.1.9\"\n },\n \"bin\": {\n \"sucrase\": \"bin/sucrase\",\n \"sucrase-node\": \"bin/sucrase-node\"\n },\n \"engines\": {\n \"node\": \">=16 || 14 >=14.17\"\n }\n },\n \"node_modules/sucrase/node_modules/commander\": {\n \"version\": \"4.1.1\",\n \"resolved\": \"https://registry.npmjs.org/commander/-/commander-4.1.1.tgz\",\n \"integrity\": \"sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">= 6\"\n }\n },\n \"node_modules/sylvester\": {\n \"version\": \"0.0.12\",\n \"resolved\": \"https://registry.npmjs.org/sylvester/-/sylvester-0.0.12.tgz\",\n \"integrity\": \"sha512-SzRP5LQ6Ts2G5NyAa/jg16s8e3R7rfdFjizy1zeoecYWw+nGL+YA1xZvW/+iJmidBGSdLkuvdwTYEyJEb+EiUw==\",\n \"engines\": {\n \"node\": \">=0.2.6\"\n }\n },\n \"node_modules/tar\": {\n \"version\": \"6.2.1\",\n \"resolved\": \"https://registry.npmjs.org/tar/-/tar-6.2.1.tgz\",\n \"integrity\": \"sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==\",\n \"deprecated\": \"Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"chownr\": \"^2.0.0\",\n \"fs-minipass\": \"^2.0.0\",\n \"minipass\": \"^5.0.0\",\n \"minizlib\": \"^2.1.1\",\n \"mkdirp\": \"^1.0.3\",\n \"yallist\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/tar/node_modules/minipass\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz\",\n \"integrity\": \"sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/thenify\": {\n \"version\": \"3.3.1\",\n \"resolved\": \"https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz\",\n \"integrity\": \"sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"any-promise\": \"^1.0.0\"\n }\n },\n \"node_modules/thenify-all\": {\n \"version\": \"1.6.0\",\n \"resolved\": \"https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz\",\n \"integrity\": \"sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"thenify\": \">= 3.1.0 < 4\"\n },\n \"engines\": {\n \"node\": \">=0.8\"\n }\n },\n \"node_modules/tinybench\": {\n \"version\": \"2.9.0\",\n \"resolved\": \"https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz\",\n \"integrity\": \"sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/tinyexec\": {\n \"version\": \"0.3.2\",\n \"resolved\": \"https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz\",\n \"integrity\": \"sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/tinyglobby\": {\n \"version\": \"0.2.15\",\n \"resolved\": \"https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz\",\n \"integrity\": \"sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"fdir\": \"^6.5.0\",\n \"picomatch\": \"^4.0.3\"\n },\n \"engines\": {\n \"node\": \">=12.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/SuperchupuDev\"\n }\n },\n \"node_modules/tinypool\": {\n \"version\": \"0.8.4\",\n \"resolved\": \"https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz\",\n \"integrity\": \"sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=14.0.0\"\n }\n },\n \"node_modules/tinyspy\": {\n \"version\": \"2.2.1\",\n \"resolved\": \"https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz\",\n \"integrity\": \"sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=14.0.0\"\n }\n },\n \"node_modules/toad-cache\": {\n \"version\": \"3.7.0\",\n \"resolved\": \"https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz\",\n \"integrity\": \"sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/toidentifier\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz\",\n \"integrity\": \"sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.6\"\n }\n },\n \"node_modules/tr46\": {\n \"version\": \"5.1.1\",\n \"resolved\": \"https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz\",\n \"integrity\": \"sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"punycode\": \"^2.3.1\"\n },\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/tree-kill\": {\n \"version\": \"1.2.2\",\n \"resolved\": \"https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz\",\n \"integrity\": \"sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"bin\": {\n \"tree-kill\": \"cli.js\"\n }\n },\n \"node_modules/ts-interface-checker\": {\n \"version\": \"0.1.13\",\n \"resolved\": \"https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz\",\n \"integrity\": \"sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==\",\n \"dev\": true,\n \"license\": \"Apache-2.0\"\n },\n \"node_modules/tsup\": {\n \"version\": \"8.5.1\",\n \"resolved\": \"https://registry.npmjs.org/tsup/-/tsup-8.5.1.tgz\",\n \"integrity\": \"sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"bundle-require\": \"^5.1.0\",\n \"cac\": \"^6.7.14\",\n \"chokidar\": \"^4.0.3\",\n \"consola\": \"^3.4.0\",\n \"debug\": \"^4.4.0\",\n \"esbuild\": \"^0.27.0\",\n \"fix-dts-default-cjs-exports\": \"^1.0.0\",\n \"joycon\": \"^3.1.1\",\n \"picocolors\": \"^1.1.1\",\n \"postcss-load-config\": \"^6.0.1\",\n \"resolve-from\": \"^5.0.0\",\n \"rollup\": \"^4.34.8\",\n \"source-map\": \"^0.7.6\",\n \"sucrase\": \"^3.35.0\",\n \"tinyexec\": \"^0.3.2\",\n \"tinyglobby\": \"^0.2.11\",\n \"tree-kill\": \"^1.2.2\"\n },\n \"bin\": {\n \"tsup\": \"dist/cli-default.js\",\n \"tsup-node\": \"dist/cli-node.js\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"peerDependencies\": {\n \"@microsoft/api-extractor\": \"^7.36.0\",\n \"@swc/core\": \"^1\",\n \"postcss\": \"^8.4.12\",\n \"typescript\": \">=4.5.0\"\n },\n \"peerDependenciesMeta\": {\n \"@microsoft/api-extractor\": {\n \"optional\": true\n },\n \"@swc/core\": {\n \"optional\": true\n },\n \"postcss\": {\n \"optional\": true\n },\n \"typescript\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/type-detect\": {\n \"version\": \"4.1.0\",\n \"resolved\": \"https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz\",\n \"integrity\": \"sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/type-is\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz\",\n \"integrity\": \"sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"content-type\": \"^1.0.5\",\n \"media-typer\": \"^1.1.0\",\n \"mime-types\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/typescript\": {\n \"version\": \"5.9.3\",\n \"resolved\": \"https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz\",\n \"integrity\": \"sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==\",\n \"devOptional\": true,\n \"license\": \"Apache-2.0\",\n \"bin\": {\n \"tsc\": \"bin/tsc\",\n \"tsserver\": \"bin/tsserver\"\n },\n \"engines\": {\n \"node\": \">=14.17\"\n }\n },\n \"node_modules/ufo\": {\n \"version\": \"1.6.3\",\n \"resolved\": \"https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz\",\n \"integrity\": \"sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/underscore\": {\n \"version\": \"1.13.7\",\n \"resolved\": \"https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz\",\n \"integrity\": \"sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==\",\n \"license\": \"MIT\"\n },\n \"node_modules/undici-types\": {\n \"version\": \"6.21.0\",\n \"resolved\": \"https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz\",\n \"integrity\": \"sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/universal-github-app-jwt\": {\n \"version\": \"2.2.2\",\n \"resolved\": \"https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-2.2.2.tgz\",\n \"integrity\": \"sha512-dcmbeSrOdTnsjGjUfAlqNDJrhxXizjAz94ija9Qw8YkZ1uu0d+GoZzyH+Jb9tIIqvGsadUfwg+22k5aDqqwzbw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/universal-user-agent\": {\n \"version\": \"7.0.3\",\n \"resolved\": \"https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz\",\n \"integrity\": \"sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/universalify\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz\",\n \"integrity\": \"sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 10.0.0\"\n }\n },\n \"node_modules/unpipe\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz\",\n \"integrity\": \"sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/url-join\": {\n \"version\": \"4.0.1\",\n \"resolved\": \"https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz\",\n \"integrity\": \"sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/util-deprecate\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz\",\n \"integrity\": \"sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/uuid\": {\n \"version\": \"9.0.1\",\n \"resolved\": \"https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz\",\n \"integrity\": \"sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==\",\n \"funding\": [\n \"https://github.com/sponsors/broofa\",\n \"https://github.com/sponsors/ctavan\"\n ],\n \"license\": \"MIT\",\n \"bin\": {\n \"uuid\": \"dist/bin/uuid\"\n }\n },\n \"node_modules/validate-npm-package-name\": {\n \"version\": \"6.0.2\",\n \"resolved\": \"https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.2.tgz\",\n \"integrity\": \"sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"^18.17.0 || >=20.5.0\"\n }\n },\n \"node_modules/vary\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/vary/-/vary-1.1.2.tgz\",\n \"integrity\": \"sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/vite\": {\n \"version\": \"5.4.21\",\n \"resolved\": \"https://registry.npmjs.org/vite/-/vite-5.4.21.tgz\",\n \"integrity\": \"sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"esbuild\": \"^0.21.3\",\n \"postcss\": \"^8.4.43\",\n \"rollup\": \"^4.20.0\"\n },\n \"bin\": {\n \"vite\": \"bin/vite.js\"\n },\n \"engines\": {\n \"node\": \"^18.0.0 || >=20.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/vitejs/vite?sponsor=1\"\n },\n \"optionalDependencies\": {\n \"fsevents\": \"~2.3.3\"\n },\n \"peerDependencies\": {\n \"@types/node\": \"^18.0.0 || >=20.0.0\",\n \"less\": \"*\",\n \"lightningcss\": \"^1.21.0\",\n \"sass\": \"*\",\n \"sass-embedded\": \"*\",\n \"stylus\": \"*\",\n \"sugarss\": \"*\",\n \"terser\": \"^5.4.0\"\n },\n \"peerDependenciesMeta\": {\n \"@types/node\": {\n \"optional\": true\n },\n \"less\": {\n \"optional\": true\n },\n \"lightningcss\": {\n \"optional\": true\n },\n \"sass\": {\n \"optional\": true\n },\n \"sass-embedded\": {\n \"optional\": true\n },\n \"stylus\": {\n \"optional\": true\n },\n \"sugarss\": {\n \"optional\": true\n },\n \"terser\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/vite-node\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/vite-node/-/vite-node-1.6.1.tgz\",\n \"integrity\": \"sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"cac\": \"^6.7.14\",\n \"debug\": \"^4.3.4\",\n \"pathe\": \"^1.1.1\",\n \"picocolors\": \"^1.0.0\",\n \"vite\": \"^5.0.0\"\n },\n \"bin\": {\n \"vite-node\": \"vite-node.mjs\"\n },\n \"engines\": {\n \"node\": \"^18.0.0 || >=20.0.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/vite-node/node_modules/pathe\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz\",\n \"integrity\": \"sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/vite/node_modules/@esbuild/aix-ppc64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz\",\n \"integrity\": \"sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"aix\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/android-arm\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz\",\n \"integrity\": \"sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/android-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/android-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/darwin-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/darwin-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/freebsd-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/freebsd-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-arm\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz\",\n \"integrity\": \"sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-ia32\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz\",\n \"integrity\": \"sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-loong64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz\",\n \"integrity\": \"sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==\",\n \"cpu\": [\n \"loong64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-mips64el\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz\",\n \"integrity\": \"sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==\",\n \"cpu\": [\n \"mips64el\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-ppc64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz\",\n \"integrity\": \"sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-riscv64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz\",\n \"integrity\": \"sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==\",\n \"cpu\": [\n \"riscv64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-s390x\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz\",\n \"integrity\": \"sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==\",\n \"cpu\": [\n \"s390x\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/netbsd-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"netbsd\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/openbsd-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openbsd\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/sunos-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"sunos\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/win32-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/win32-ia32\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz\",\n \"integrity\": \"sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/win32-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/esbuild\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz\",\n \"integrity\": \"sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==\",\n \"dev\": true,\n \"hasInstallScript\": true,\n \"license\": \"MIT\",\n \"bin\": {\n \"esbuild\": \"bin/esbuild\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"optionalDependencies\": {\n \"@esbuild/aix-ppc64\": \"0.21.5\",\n \"@esbuild/android-arm\": \"0.21.5\",\n \"@esbuild/android-arm64\": \"0.21.5\",\n \"@esbuild/android-x64\": \"0.21.5\",\n \"@esbuild/darwin-arm64\": \"0.21.5\",\n \"@esbuild/darwin-x64\": \"0.21.5\",\n \"@esbuild/freebsd-arm64\": \"0.21.5\",\n \"@esbuild/freebsd-x64\": \"0.21.5\",\n \"@esbuild/linux-arm\": \"0.21.5\",\n \"@esbuild/linux-arm64\": \"0.21.5\",\n \"@esbuild/linux-ia32\": \"0.21.5\",\n \"@esbuild/linux-loong64\": \"0.21.5\",\n \"@esbuild/linux-mips64el\": \"0.21.5\",\n \"@esbuild/linux-ppc64\": \"0.21.5\",\n \"@esbuild/linux-riscv64\": \"0.21.5\",\n \"@esbuild/linux-s390x\": \"0.21.5\",\n \"@esbuild/linux-x64\": \"0.21.5\",\n \"@esbuild/netbsd-x64\": \"0.21.5\",\n \"@esbuild/openbsd-x64\": \"0.21.5\",\n \"@esbuild/sunos-x64\": \"0.21.5\",\n \"@esbuild/win32-arm64\": \"0.21.5\",\n \"@esbuild/win32-ia32\": \"0.21.5\",\n \"@esbuild/win32-x64\": \"0.21.5\"\n }\n },\n \"node_modules/vitest\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/vitest/-/vitest-1.6.1.tgz\",\n \"integrity\": \"sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@vitest/expect\": \"1.6.1\",\n \"@vitest/runner\": \"1.6.1\",\n \"@vitest/snapshot\": \"1.6.1\",\n \"@vitest/spy\": \"1.6.1\",\n \"@vitest/utils\": \"1.6.1\",\n \"acorn-walk\": \"^8.3.2\",\n \"chai\": \"^4.3.10\",\n \"debug\": \"^4.3.4\",\n \"execa\": \"^8.0.1\",\n \"local-pkg\": \"^0.5.0\",\n \"magic-string\": \"^0.30.5\",\n \"pathe\": \"^1.1.1\",\n \"picocolors\": \"^1.0.0\",\n \"std-env\": \"^3.5.0\",\n \"strip-literal\": \"^2.0.0\",\n \"tinybench\": \"^2.5.1\",\n \"tinypool\": \"^0.8.3\",\n \"vite\": \"^5.0.0\",\n \"vite-node\": \"1.6.1\",\n \"why-is-node-running\": \"^2.2.2\"\n },\n \"bin\": {\n \"vitest\": \"vitest.mjs\"\n },\n \"engines\": {\n \"node\": \"^18.0.0 || >=20.0.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n },\n \"peerDependencies\": {\n \"@edge-runtime/vm\": \"*\",\n \"@types/node\": \"^18.0.0 || >=20.0.0\",\n \"@vitest/browser\": \"1.6.1\",\n \"@vitest/ui\": \"1.6.1\",\n \"happy-dom\": \"*\",\n \"jsdom\": \"*\"\n },\n \"peerDependenciesMeta\": {\n \"@edge-runtime/vm\": {\n \"optional\": true\n },\n \"@types/node\": {\n \"optional\": true\n },\n \"@vitest/browser\": {\n \"optional\": true\n },\n \"@vitest/ui\": {\n \"optional\": true\n },\n \"happy-dom\": {\n \"optional\": true\n },\n \"jsdom\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/vitest/node_modules/pathe\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz\",\n \"integrity\": \"sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/webidl-conversions\": {\n \"version\": \"7.0.0\",\n \"resolved\": \"https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz\",\n \"integrity\": \"sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==\",\n \"license\": \"BSD-2-Clause\",\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/whatwg-url\": {\n \"version\": \"14.2.0\",\n \"resolved\": \"https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz\",\n \"integrity\": \"sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"tr46\": \"^5.1.0\",\n \"webidl-conversions\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/which\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/which/-/which-2.0.2.tgz\",\n \"integrity\": \"sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"isexe\": \"^2.0.0\"\n },\n \"bin\": {\n \"node-which\": \"bin/node-which\"\n },\n \"engines\": {\n \"node\": \">= 8\"\n }\n },\n \"node_modules/why-is-node-running\": {\n \"version\": \"2.3.0\",\n \"resolved\": \"https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz\",\n \"integrity\": \"sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"siginfo\": \"^2.0.0\",\n \"stackback\": \"0.0.2\"\n },\n \"bin\": {\n \"why-is-node-running\": \"cli.js\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wide-align\": {\n \"version\": \"1.1.5\",\n \"resolved\": \"https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz\",\n \"integrity\": \"sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"string-width\": \"^1.0.2 || 2 || 3 || 4\"\n }\n },\n \"node_modules/wide-align/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wide-align/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/wide-align/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wide-align/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wordnet-db\": {\n \"version\": \"3.1.14\",\n \"resolved\": \"https://registry.npmjs.org/wordnet-db/-/wordnet-db-3.1.14.tgz\",\n \"integrity\": \"sha512-zVyFsvE+mq9MCmwXUWHIcpfbrHHClZWZiVOzKSxNJruIcFn2RbY55zkhiAMMxM8zCVSmtNiViq8FsAZSFpMYag==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.6.0\"\n }\n },\n \"node_modules/wrap-ansi\": {\n \"version\": \"8.1.0\",\n \"resolved\": \"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz\",\n \"integrity\": \"sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-styles\": \"^6.1.0\",\n \"string-width\": \"^5.0.1\",\n \"strip-ansi\": \"^7.0.1\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/wrap-ansi?sponsor=1\"\n }\n },\n \"node_modules/wrap-ansi-cjs\": {\n \"name\": \"wrap-ansi\",\n \"version\": \"7.0.0\",\n \"resolved\": \"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz\",\n \"integrity\": \"sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-styles\": \"^4.0.0\",\n \"string-width\": \"^4.1.0\",\n \"strip-ansi\": \"^6.0.0\"\n },\n \"engines\": {\n \"node\": \">=10\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/wrap-ansi?sponsor=1\"\n }\n },\n \"node_modules/wrap-ansi-cjs/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wrap-ansi-cjs/node_modules/ansi-styles\": {\n \"version\": \"4.3.0\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz\",\n \"integrity\": \"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"color-convert\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/wrap-ansi-cjs/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\"\n },\n \"node_modules/wrap-ansi-cjs/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wrap-ansi-cjs/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wrap-ansi/node_modules/ansi-styles\": {\n \"version\": \"6.2.3\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz\",\n \"integrity\": \"sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/wrappy\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz\",\n \"integrity\": \"sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/xtend\": {\n \"version\": \"4.0.2\",\n \"resolved\": \"https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz\",\n \"integrity\": \"sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.4\"\n }\n },\n \"node_modules/y18n\": {\n \"version\": \"5.0.8\",\n \"resolved\": \"https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz\",\n \"integrity\": \"sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/yallist\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz\",\n \"integrity\": \"sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==\",\n \"license\": \"ISC\"\n },\n \"node_modules/yaml\": {\n \"version\": \"2.8.2\",\n \"resolved\": \"https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz\",\n \"integrity\": \"sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"bin\": {\n \"yaml\": \"bin.mjs\"\n },\n \"engines\": {\n \"node\": \">= 14.6\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/eemeli\"\n }\n },\n \"node_modules/yargs\": {\n \"version\": \"17.7.2\",\n \"resolved\": \"https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz\",\n \"integrity\": \"sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"cliui\": \"^8.0.1\",\n \"escalade\": \"^3.1.1\",\n \"get-caller-file\": \"^2.0.5\",\n \"require-directory\": \"^2.1.1\",\n \"string-width\": \"^4.2.3\",\n \"y18n\": \"^5.0.5\",\n \"yargs-parser\": \"^21.1.1\"\n },\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/yargs-parser\": {\n \"version\": \"21.1.1\",\n \"resolved\": \"https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz\",\n \"integrity\": \"sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/yargs/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/yargs/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/yargs/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/yargs/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/yocto-queue\": {\n \"version\": \"1.2.2\",\n \"resolved\": \"https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz\",\n \"integrity\": \"sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12.20\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/yoctocolors\": {\n \"version\": \"2.1.2\",\n \"resolved\": \"https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz\",\n \"integrity\": \"sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/zod\": {\n \"version\": \"4.3.6\",\n \"resolved\": \"https://registry.npmjs.org/zod/-/zod-4.3.6.tgz\",\n \"integrity\": \"sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"url\": \"https://github.com/sponsors/colinhacks\"\n }\n },\n \"node_modules/zod-to-json-schema\": {\n \"version\": \"3.25.1\",\n \"resolved\": \"https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz\",\n \"integrity\": \"sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"peerDependencies\": {\n \"zod\": \"^3.25 || ^4\"\n }\n }\n }\n}\n",197 "mimeType": null,198 "size": null,199 "icons": null,200 "annotations": null,201 "meta": null202 }203 ],204 "resource_templates": [],205 "tools": [206 {207 "name": "search.test.ts",208 "title": null,209 "description": "Script: search.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\n\nconst { execFileSyncMock, spawnSyncMock } = vi.hoisted(() => ({\n execFileSyncMock: vi.fn(),\n spawnSyncMock: vi.fn()\n}));\n\nvi.mock('child_process', () => ({\n execFileSync: execFileSyncMock,\n spawnSync: spawnSyncMock\n}));\n\nasync function loadSearchModule() {\n vi.resetModules();\n return await import('./search.js');\n}\n\nafterEach(() => {\n vi.clearAllMocks();\n});\n\ndescribe('search qmd dependency', () => {\n it('returns false when qmd is not available', async () => {\n spawnSyncMock.mockReturnValue({ error: new Error('missing') });\n const { hasQmd } = await loadSearchModule();\n expect(hasQmd()).toBe(false);\n });\n\n it('throws when searching without qmd installed', async () => {\n spawnSyncMock.mockReturnValue({ error: new Error('missing') });\n const { SearchEngine, QmdUnavailableError } = await loadSearchModule();\n const engine = new SearchEngine();\n expect(() => engine.search('hello')).toThrow(QmdUnavailableError);\n });\n\n it('converts qmd results and applies filters', async () => {\n spawnSyncMock.mockReturnValue({ error: undefined });\n execFileSyncMock.mockReturnValue(\n JSON.stringify([\n {\n docid: '1',\n score: 10,\n file: 'qmd://vault/projects/demo.md',\n title: 'Demo',\n snippet: '@@ -1,2 @@ (1 before, 2 after)\\nLine1\\nLine2\\nLine3\\nLine4'\n },\n {\n docid: '2',\n score: 5,\n file: 'qmd://vault/notes/other.md',\n title: 'Other',\n snippet: 'Other snippet'\n }\n ])\n );\n\n const { SearchEngine } = await loadSearchModule();\n const engine = new SearchEngine();\n engine.setCollection('vault');\n engine.setVaultPath('/vault');\n engine.setCollectionRoot('/vault');\n engine.addDocument({\n id: 'projects/demo',\n path: '/vault/projects/demo.md',\n category: 'projects',\n title: 'Demo',\n content: 'content',\n frontmatter: {},\n links: [],\n tags: ['keep'],\n modified: new Date()\n });\n\n const results = engine.search('hello', {\n tags: ['keep'],\n category: 'projects',\n limit: 5\n });\n\n expect(results).toHaveLength(1);\n expect(results[0].document.id).toBe('projects/demo');\n expect(results[0].document.path).toBe('/vault/projects/demo.md');\n expect(results[0].score).toBe(1);\n expect(results[0].snippet).not.toContain('@@');\n expect(results[0].snippet).toContain('Line1');\n });\n\n it('parses qmd output from error streams', async () => {\n spawnSyncMock.mockReturnValue({ error: undefined });\n execFileSyncMock.mockImplementation(() => {\n const err: any = new Error('qmd failed');\n err.stdout =\n 'noise\\n[{\"docid\":\"1\",\"score\":2,\"file\":\"qmd://vault/notes/a.md\",\"title\":\"A\",\"snippet\":\"hi\"}]';\n throw err;\n });\n\n const { SearchEngine } = await loadSearchModule();\n const engine = new SearchEngine();\n engine.setCollectionRoot('/vault');\n engine.setVaultPath('/vault');\n\n const results = engine.search('fallback', { limit: 1 });\n expect(results).toHaveLength(1);\n expect(results[0].document.path).toBe('/vault/notes/a.md');\n });\n});\n",210 "inputSchema": {},211 "outputSchema": null,212 "icons": null,213 "annotations": null,214 "meta": null,215 "execution": null216 },217 {218 "name": "search.ts",219 "title": null,220 "description": "Script: search.ts. Code:\n/**\n * ClawVault Search Engine - qmd Backend\n * Uses qmd CLI for BM25 and vector search\n */\n\nimport { execFileSync, spawnSync } from 'child_process';\nimport * as path from 'path';\nimport { Document, SearchResult, SearchOptions } from '../types.js';\n\nexport const QMD_INSTALL_URL = 'https://github.com/tobi/qmd';\nexport const QMD_INSTALL_COMMAND = 'bun install -g github:tobi/qmd';\nconst QMD_NOT_INSTALLED_MESSAGE = `ClawVault requires qmd. Install: ${QMD_INSTALL_COMMAND}`;\n\nexport class QmdUnavailableError extends Error {\n constructor(message: string = QMD_NOT_INSTALLED_MESSAGE) {\n super(message);\n this.name = 'QmdUnavailableError';\n }\n}\n\n/**\n * QMD search result format\n */\ninterface QmdResult {\n docid: string;\n score: number;\n file: string;\n title: string;\n snippet: string;\n}\n\nfunction ensureJsonArgs(args: string[]): string[] {\n return args.includes('--json') ? args : [...args, '--json'];\n}\n\nfunction tryParseJson(raw: string): unknown | null {\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\nfunction extractJsonPayload(raw: string): string | null {\n const start = raw.search(/[\\[{]/);\n if (start === -1) return null;\n const end = Math.max(raw.lastIndexOf(']'), raw.lastIndexOf('}'));\n if (end <= start) return null;\n return raw.slice(start, end + 1);\n}\n\nfunction parseQmdOutput(raw: string): QmdResult[] {\n const trimmed = raw.trim();\n if (!trimmed) return [];\n\n const direct = tryParseJson(trimmed);\n const extracted = direct ? null : extractJsonPayload(trimmed);\n const parsed = direct ?? (extracted ? tryParseJson(extracted) : null);\n\n if (!parsed) {\n throw new Error('qmd returned non-JSON output. Ensure qmd supports --json.');\n }\n\n if (Array.isArray(parsed)) {\n return parsed as QmdResult[];\n }\n\n if (parsed && typeof parsed === 'object') {\n const candidate = (parsed as { results?: unknown; items?: unknown; data?: unknown; }).results\n ?? (parsed as { results?: unknown; items?: unknown; data?: unknown; }).items\n ?? (parsed as { results?: unknown; items?: unknown; data?: unknown; }).data;\n\n if (Array.isArray(candidate)) {\n return candidate as QmdResult[];\n }\n }\n\n throw new Error('qmd returned an unexpected JSON shape.');\n}\n\nfunction ensureQmdAvailable(): void {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n}\n\n/**\n * Execute qmd command and return parsed JSON\n */\nfunction execQmd(args: string[]): QmdResult[] {\n ensureQmdAvailable();\n const finalArgs = ensureJsonArgs(args);\n\n try {\n const result = execFileSync('qmd', finalArgs, {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'pipe'],\n maxBuffer: 10 * 1024 * 1024 // 10MB\n });\n\n return parseQmdOutput(result);\n } catch (err: any) {\n if (err?.code === 'ENOENT') {\n throw new QmdUnavailableError();\n }\n\n const output = [err?.stdout, err?.stderr].filter(Boolean).join('\\n');\n if (output) {\n try {\n return parseQmdOutput(output);\n } catch {\n // Fall through to throw a helpful error\n }\n }\n\n const message = err?.message ? `qmd failed: ${err.message}` : 'qmd failed';\n throw new Error(message);\n }\n}\n\n/**\n * Check if qmd is available\n */\nexport function hasQmd(): boolean {\n const result = spawnSync('qmd', ['--version'], { stdio: 'ignore' });\n return !result.error;\n}\n\n/**\n * Trigger qmd update (reindex)\n */\nexport function qmdUpdate(collection?: string): void {\n ensureQmdAvailable();\n const args = ['update'];\n if (collection) {\n args.push('-c', collection);\n }\n execFileSync('qmd', args, { stdio: 'inherit' });\n}\n\n/**\n * Trigger qmd embed (create/update vector embeddings)\n */\nexport function qmdEmbed(collection?: string): void {\n ensureQmdAvailable();\n const args = ['embed'];\n if (collection) {\n args.push('-c', collection);\n }\n execFileSync('qmd', args, { stdio: 'inherit' });\n}\n\n/**\n * QMD Search Engine - wraps qmd CLI\n */\nexport class SearchEngine {\n private documents: Map<string, Document> = new Map();\n private collection: string = 'clawvault';\n private vaultPath: string = '';\n private collectionRoot: string = '';\n\n /**\n * Set the collection name (usually vault name)\n */\n setCollection(name: string): void {\n this.collection = name;\n }\n\n /**\n * Set the vault path for file resolution\n */\n setVaultPath(vaultPath: string): void {\n this.vaultPath = vaultPath;\n }\n\n /**\n * Set the collection root for qmd:// URI resolution\n */\n setCollectionRoot(root: string): void {\n this.collectionRoot = path.resolve(root);\n }\n\n /**\n * Add or update a document in the local cache\n * Note: qmd indexing happens via qmd update command\n */\n addDocument(doc: Document): void {\n this.documents.set(doc.id, doc);\n }\n\n /**\n * Remove a document from the local cache\n */\n removeDocument(id: string): void {\n this.documents.delete(id);\n }\n\n /**\n * No-op for qmd - indexing is managed externally\n */\n rebuildIDF(): void {\n // qmd handles this\n }\n\n /**\n * BM25 search via qmd\n */\n search(query: string, options: SearchOptions = {}): SearchResult[] {\n return this.runQmdQuery('search', query, options);\n }\n\n /**\n * Vector/semantic search via qmd vsearch\n */\n vsearch(query: string, options: SearchOptions = {}): SearchResult[] {\n return this.runQmdQuery('vsearch', query, options);\n }\n\n /**\n * Combined search with query expansion (qmd query command)\n */\n query(query: string, options: SearchOptions = {}): SearchResult[] {\n return this.runQmdQuery('query', query, options);\n }\n\n private runQmdQuery(command: 'search' | 'vsearch' | 'query', query: string, options: SearchOptions): SearchResult[] {\n const {\n limit = 10,\n minScore = 0,\n category,\n tags,\n fullContent = false\n } = options;\n\n if (!query.trim()) return [];\n\n const args = [\n command,\n query,\n '-n', String(limit * 2),\n '--json'\n ];\n\n if (this.collection) {\n args.push('-c', this.collection);\n }\n\n const qmdResults = execQmd(args);\n\n return this.convertResults(qmdResults, {\n limit,\n minScore,\n category,\n tags,\n fullContent\n });\n }\n\n /**\n * Convert qmd results to ClawVault SearchResult format\n */\n private convertResults(\n qmdResults: QmdResult[], \n options: SearchOptions\n ): SearchResult[] {\n const { limit = 10, minScore = 0, category, tags, fullContent = false } = options;\n \n const results: SearchResult[] = [];\n \n // Normalize scores - qmd uses different scales\n const maxScore = qmdResults[0]?.score || 1;\n \n for (const qr of qmdResults) {\n // Extract file path from qmd:// URI\n const filePath = this.qmdUriToPath(qr.file);\n const relativePath = this.vaultPath \n ? path.relative(this.vaultPath, filePath)\n : filePath;\n \n // Get document from cache or create minimal one\n const docId = relativePath.replace(/\\.md$/, '');\n let doc = this.documents.get(docId);\n \n // Determine category from path\n const parts = relativePath.split(path.sep);\n const docCategory = parts.length > 1 ? parts[0] : 'root';\n \n // Apply category filter\n if (category && docCategory !== category) continue;\n \n // Apply tag filter (only if we have the document cached)\n if (tags && tags.length > 0 && doc) {\n const docTags = new Set(doc.tags);\n if (!tags.some(t => docTags.has(t))) continue;\n }\n \n // Normalize score to 0-1 range\n const normalizedScore = maxScore > 0 ? qr.score / maxScore : 0;\n \n // Apply min score filter\n if (normalizedScore < minScore) continue;\n \n // Create document if not cached\n if (!doc) {\n doc = {\n id: docId,\n path: filePath,\n category: docCategory,\n title: qr.title || path.basename(relativePath, '.md'),\n content: '', // Content loaded separately if needed\n frontmatter: {},\n links: [],\n tags: [],\n modified: new Date()\n };\n }\n \n results.push({\n document: fullContent ? doc : { ...doc, content: '' },\n score: normalizedScore,\n snippet: this.cleanSnippet(qr.snippet),\n matchedTerms: [] // qmd doesn't provide this\n });\n \n if (results.length >= limit) break;\n }\n \n return results;\n }\n\n /**\n * Convert qmd:// URI to file path\n */\n private qmdUriToPath(uri: string): string {\n // qmd://collection/path/to/file.md -> actual path\n if (uri.startsWith('qmd://')) {\n const withoutScheme = uri.slice(6); // Remove 'qmd://'\n const slashIndex = withoutScheme.indexOf('/');\n if (slashIndex > -1) {\n // Get collection name and relative path\n const relativePath = withoutScheme.slice(slashIndex + 1);\n\n const root = this.collectionRoot || this.vaultPath;\n if (root) {\n return path.join(root, relativePath);\n }\n\n return relativePath;\n }\n }\n \n // Return as-is if not a qmd:// URI\n return uri;\n }\n\n /**\n * Clean up qmd snippet format\n */\n private cleanSnippet(snippet: string): string {\n if (!snippet) return '';\n \n // Remove diff-style markers like \"@@ -2,4 @@ (1 before, 67 after)\"\n return snippet\n .replace(/@@ [-+]?\\d+,?\\d* @@ \\([^)]+\\)/g, '')\n .trim()\n .split('\\n')\n .slice(0, 3)\n .join('\\n')\n .slice(0, 300);\n }\n\n /**\n * Get all cached documents\n */\n getAllDocuments(): Document[] {\n return [...this.documents.values()];\n }\n\n /**\n * Get document count\n */\n get size(): number {\n return this.documents.size;\n }\n\n /**\n * Clear the local document cache\n */\n clear(): void {\n this.documents.clear();\n }\n\n /**\n * Export documents for persistence\n */\n export(): { documents: Document[]; } {\n return {\n documents: [...this.documents.values()]\n };\n }\n\n /**\n * Import from persisted data\n */\n import(data: { documents: Document[]; }): void {\n this.clear();\n for (const doc of data.documents) {\n this.addDocument(doc);\n }\n }\n}\n\n/**\n * Find wiki-links in content\n */\nexport function extractWikiLinks(content: string): string[] {\n const matches = content.match(/\\[\\[([^\\]]+)\\]\\]/g) || [];\n return matches.map(m => m.slice(2, -2).toLowerCase());\n}\n\n/**\n * Find tags in content (#tag format)\n */\nexport function extractTags(content: string): string[] {\n const matches = content.match(/#[\\w-]+/g) || [];\n return [...new Set(matches.map(m => m.slice(1).toLowerCase()))];\n}\n",221 "inputSchema": {},222 "outputSchema": null,223 "icons": null,224 "annotations": null,225 "meta": null,226 "execution": null227 },228 {229 "name": "entity-index.ts",230 "title": null,231 "description": "Script: entity-index.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport matter from 'gray-matter';\n\nexport interface EntityEntry {\n path: string; // Relative path without .md (e.g., \"people/pedro\")\n aliases: string[]; // All names that link to this entity\n}\n\nexport interface EntityIndex {\n entries: Map<string, string>; // lowercase alias -> path\n byPath: Map<string, EntityEntry>;\n}\n\n/**\n * Build an entity index from all markdown files in the vault.\n * Extracts linkable names from:\n * - Filename (without .md)\n * - Frontmatter `title` field\n * - Frontmatter `aliases` array\n */\nexport function buildEntityIndex(vaultPath: string): EntityIndex {\n const entries = new Map<string, string>();\n const byPath = new Map<string, EntityEntry>();\n \n // Folders to scan for entities\n const entityFolders = ['people', 'projects', 'agents', 'lessons', 'decisions', 'commitments'];\n \n for (const folder of entityFolders) {\n const folderPath = path.join(vaultPath, folder);\n if (!fs.existsSync(folderPath)) continue;\n \n const files = fs.readdirSync(folderPath).filter(f => f.endsWith('.md'));\n \n for (const file of files) {\n const filePath = path.join(folderPath, file);\n const content = fs.readFileSync(filePath, 'utf-8');\n const { data: frontmatter } = matter(content);\n \n const relativePath = `${folder}/${file.replace('.md', '')}`;\n const baseName = file.replace('.md', '');\n \n const aliases: string[] = [baseName];\n \n // Add title if different from filename\n if (frontmatter.title && frontmatter.title.toLowerCase() !== baseName.toLowerCase()) {\n aliases.push(frontmatter.title);\n }\n \n // Add explicit aliases\n if (Array.isArray(frontmatter.aliases)) {\n aliases.push(...frontmatter.aliases);\n }\n \n // Register all aliases\n for (const alias of aliases) {\n const key = alias.toLowerCase();\n if (!entries.has(key)) {\n entries.set(key, relativePath);\n }\n }\n \n byPath.set(relativePath, { path: relativePath, aliases });\n }\n }\n \n return { entries, byPath };\n}\n\n/**\n * Get all entities sorted by alias length (longest first)\n * This ensures \"Justin Dukes\" is matched before \"Justin\"\n */\nexport function getSortedAliases(index: EntityIndex): Array<{ alias: string; path: string }> {\n const result: Array<{ alias: string; path: string }> = [];\n \n for (const [alias, path] of index.entries) {\n result.push({ alias, path });\n }\n \n // Sort by length descending\n result.sort((a, b) => b.alias.length - a.alias.length);\n \n return result;\n}\n",232 "inputSchema": {},233 "outputSchema": null,234 "icons": null,235 "annotations": null,236 "meta": null,237 "execution": null238 },239 {240 "name": "config.ts",241 "title": null,242 "description": "Script: config.ts. Code:\nimport * as path from 'path';\n\n/**\n * Get the vault path from CLAWVAULT_PATH env var or throw\n */\nexport function getVaultPath(): string {\n const vaultPath = process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n throw new Error('CLAWVAULT_PATH environment variable not set');\n }\n return path.resolve(vaultPath);\n}\n",243 "inputSchema": {},244 "outputSchema": null,245 "icons": null,246 "annotations": null,247 "meta": null,248 "execution": null249 },250 {251 "name": "vault.ts",252 "title": null,253 "description": "Script: vault.ts. Code:\n/**\n * ClawVault - The elephant's memory\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport matter from 'gray-matter';\nimport { glob } from 'glob';\nimport {\n VaultConfig,\n VaultMeta,\n Document,\n SearchResult,\n SearchOptions,\n StoreOptions,\n SyncOptions,\n SyncResult,\n DEFAULT_CATEGORIES,\n Category,\n MemoryType,\n TYPE_TO_CATEGORY,\n HandoffDocument,\n SessionRecap\n} from '../types.js';\nimport { SearchEngine, extractWikiLinks, extractTags, hasQmd, qmdUpdate, qmdEmbed, QmdUnavailableError } from './search.js';\n\nconst CONFIG_FILE = '.clawvault.json';\nconst INDEX_FILE = '.clawvault-index.json';\n\nexport class ClawVault {\n private config: VaultConfig;\n private search: SearchEngine;\n private initialized: boolean = false;\n\n constructor(vaultPath: string) {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n this.config = {\n path: path.resolve(vaultPath),\n name: path.basename(vaultPath),\n categories: DEFAULT_CATEGORIES,\n qmdCollection: undefined,\n qmdRoot: undefined\n };\n this.search = new SearchEngine();\n this.applyQmdConfig();\n }\n\n /**\n * Initialize a new vault\n */\n async init(options: Partial<VaultConfig> = {}): Promise<void> {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vaultPath = this.config.path;\n \n // Merge options\n this.config = { ...this.config, ...options };\n this.applyQmdConfig();\n \n // Create vault directory\n if (!fs.existsSync(vaultPath)) {\n fs.mkdirSync(vaultPath, { recursive: true });\n }\n\n // Create category directories\n for (const category of this.config.categories) {\n const catPath = path.join(vaultPath, category);\n if (!fs.existsSync(catPath)) {\n fs.mkdirSync(catPath, { recursive: true });\n }\n }\n\n // Create templates\n await this.createTemplates();\n\n // Create README\n const readmePath = path.join(vaultPath, 'README.md');\n if (!fs.existsSync(readmePath)) {\n fs.writeFileSync(readmePath, this.generateReadme());\n }\n\n // Save config\n const configPath = path.join(vaultPath, CONFIG_FILE);\n const meta: VaultMeta = {\n name: this.config.name,\n version: '1.0.0',\n created: new Date().toISOString(),\n lastUpdated: new Date().toISOString(),\n categories: this.config.categories,\n documentCount: 0,\n qmdCollection: this.getQmdCollection(),\n qmdRoot: this.getQmdRoot()\n };\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n\n this.initialized = true;\n }\n\n /**\n * Load an existing vault\n */\n async load(): Promise<void> {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vaultPath = this.config.path;\n const configPath = path.join(vaultPath, CONFIG_FILE);\n\n if (!fs.existsSync(configPath)) {\n throw new Error(`Not a ClawVault: ${vaultPath} (missing ${CONFIG_FILE})`);\n }\n\n const meta: VaultMeta = JSON.parse(fs.readFileSync(configPath, 'utf-8'));\n this.config.name = meta.name;\n this.config.categories = meta.categories;\n this.config.qmdCollection = meta.qmdCollection;\n this.config.qmdRoot = meta.qmdRoot;\n\n if (!meta.qmdCollection || !meta.qmdRoot) {\n meta.qmdCollection = meta.qmdCollection || meta.name;\n meta.qmdRoot = meta.qmdRoot || this.config.path;\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n }\n\n // Configure search engine with vault info\n this.applyQmdConfig(meta);\n\n // Index all documents (local cache)\n await this.reindex();\n this.initialized = true;\n }\n\n /**\n * Reindex all documents\n */\n async reindex(): Promise<number> {\n this.search.clear();\n \n const files = await glob('**/*.md', {\n cwd: this.config.path,\n ignore: ['**/node_modules/**', '**/.*']\n });\n\n for (const file of files) {\n const doc = await this.loadDocument(file);\n if (doc) {\n this.search.addDocument(doc);\n }\n }\n\n // Save index\n await this.saveIndex();\n\n return this.search.size;\n }\n\n /**\n * Load a document from disk\n */\n private async loadDocument(relativePath: string): Promise<Document | null> {\n try {\n const fullPath = path.join(this.config.path, relativePath);\n const content = fs.readFileSync(fullPath, 'utf-8');\n const { data: frontmatter, content: body } = matter(content);\n const stats = fs.statSync(fullPath);\n\n const parts = relativePath.split(path.sep);\n const category = parts.length > 1 ? parts[0] : 'root';\n const filename = path.basename(relativePath, '.md');\n\n return {\n id: relativePath.replace(/\\.md$/, ''),\n path: fullPath,\n category,\n title: (frontmatter.title as string) || filename,\n content: body,\n frontmatter,\n links: extractWikiLinks(body),\n tags: extractTags(body),\n modified: stats.mtime\n };\n } catch (err) {\n console.error(`Error loading ${relativePath}:`, err);\n return null;\n }\n }\n\n /**\n * Store a new document\n */\n async store(options: StoreOptions): Promise<Document> {\n const { \n category, \n title, \n content, \n frontmatter = {}, \n overwrite = false,\n qmdUpdate: triggerUpdate = false,\n qmdEmbed: triggerEmbed = false\n } = options;\n\n // Create filename from title\n const filename = this.slugify(title) + '.md';\n const relativePath = path.join(category, filename);\n const fullPath = path.join(this.config.path, relativePath);\n\n // Check if exists\n if (fs.existsSync(fullPath) && !overwrite) {\n throw new Error(`Document already exists: ${relativePath}. Use overwrite: true to replace.`);\n }\n\n // Ensure category directory exists\n const categoryPath = path.join(this.config.path, category);\n if (!fs.existsSync(categoryPath)) {\n fs.mkdirSync(categoryPath, { recursive: true });\n }\n\n // Build frontmatter with date\n const fm = {\n title,\n date: new Date().toISOString().split('T')[0],\n ...frontmatter\n };\n\n // Write file\n const fileContent = matter.stringify(content, fm);\n fs.writeFileSync(fullPath, fileContent);\n\n // Load and index the document\n const doc = await this.loadDocument(relativePath);\n if (doc) {\n this.search.addDocument(doc);\n await this.saveIndex();\n }\n\n // Trigger qmd reindex if requested\n if (triggerUpdate || triggerEmbed) {\n qmdUpdate(this.getQmdCollection());\n if (triggerEmbed) {\n qmdEmbed(this.getQmdCollection());\n }\n }\n\n return doc!;\n }\n\n /**\n * Quick store to inbox\n */\n async capture(note: string, title?: string): Promise<Document> {\n const autoTitle = title || `note-${Date.now()}`;\n return this.store({\n category: 'inbox',\n title: autoTitle,\n content: note\n });\n }\n\n /**\n * Search the vault (BM25 via qmd)\n */\n async find(query: string, options: SearchOptions = {}): Promise<SearchResult[]> {\n return this.search.search(query, options);\n }\n\n /**\n * Semantic/vector search (via qmd vsearch)\n */\n async vsearch(query: string, options: SearchOptions = {}): Promise<SearchResult[]> {\n return this.search.vsearch(query, options);\n }\n\n /**\n * Combined search with query expansion (via qmd query)\n */\n async query(query: string, options: SearchOptions = {}): Promise<SearchResult[]> {\n return this.search.query(query, options);\n }\n\n /**\n * Get a document by ID or path\n */\n async get(idOrPath: string): Promise<Document | null> {\n // Normalize path\n const normalized = idOrPath.replace(/\\.md$/, '');\n const docs = this.search.getAllDocuments();\n return docs.find(d => d.id === normalized) || null;\n }\n\n /**\n * List documents in a category\n */\n async list(category?: string): Promise<Document[]> {\n const docs = this.search.getAllDocuments();\n if (category) {\n return docs.filter(d => d.category === category);\n }\n return docs;\n }\n\n /**\n * Sync vault to another location (for Obsidian on Windows, etc.)\n */\n async sync(options: SyncOptions): Promise<SyncResult> {\n const { target, deleteOrphans = false, dryRun = false } = options;\n const result: SyncResult = {\n copied: [],\n deleted: [],\n unchanged: [],\n errors: []\n };\n\n // Get all source files\n const sourceFiles = await glob('**/*.md', {\n cwd: this.config.path,\n ignore: ['**/node_modules/**']\n });\n\n // Ensure target exists\n if (!dryRun && !fs.existsSync(target)) {\n fs.mkdirSync(target, { recursive: true });\n }\n\n // Copy files\n for (const file of sourceFiles) {\n const sourcePath = path.join(this.config.path, file);\n const targetPath = path.join(target, file);\n\n try {\n const sourceStats = fs.statSync(sourcePath);\n let shouldCopy = true;\n\n if (fs.existsSync(targetPath)) {\n const targetStats = fs.statSync(targetPath);\n if (sourceStats.mtime <= targetStats.mtime) {\n result.unchanged.push(file);\n shouldCopy = false;\n }\n }\n\n if (shouldCopy) {\n if (!dryRun) {\n const targetDir = path.dirname(targetPath);\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n fs.copyFileSync(sourcePath, targetPath);\n }\n result.copied.push(file);\n }\n } catch (err) {\n result.errors.push(`${file}: ${err}`);\n }\n }\n\n // Handle orphans in target\n if (deleteOrphans) {\n const targetFiles = await glob('**/*.md', { cwd: target });\n const sourceSet = new Set(sourceFiles);\n \n for (const file of targetFiles) {\n if (!sourceSet.has(file)) {\n if (!dryRun) {\n fs.unlinkSync(path.join(target, file));\n }\n result.deleted.push(file);\n }\n }\n }\n\n return result;\n }\n\n /**\n * Get vault statistics\n */\n async stats(): Promise<{\n documents: number;\n categories: { [key: string]: number };\n links: number;\n tags: string[];\n }> {\n const docs = this.search.getAllDocuments();\n const categories: { [key: string]: number } = {};\n const allTags = new Set<string>();\n let totalLinks = 0;\n\n for (const doc of docs) {\n categories[doc.category] = (categories[doc.category] || 0) + 1;\n totalLinks += doc.links.length;\n doc.tags.forEach(t => allTags.add(t));\n }\n\n return {\n documents: docs.length,\n categories,\n links: totalLinks,\n tags: [...allTags].sort()\n };\n }\n\n /**\n * Get all categories\n */\n getCategories(): Category[] {\n return this.config.categories;\n }\n\n /**\n * Check if vault is initialized\n */\n isInitialized(): boolean {\n return this.initialized;\n }\n\n /**\n * Get vault path\n */\n getPath(): string {\n return this.config.path;\n }\n\n /**\n * Get vault name\n */\n getName(): string {\n return this.config.name;\n }\n\n /**\n * Get qmd collection name\n */\n getQmdCollection(): string {\n return this.config.qmdCollection || this.config.name;\n }\n\n /**\n * Get qmd collection root\n */\n getQmdRoot(): string {\n return this.config.qmdRoot || this.config.path;\n }\n\n // === Memory Type System ===\n\n /**\n * Store a memory with type classification\n * Automatically routes to correct category based on type\n */\n async remember(\n type: MemoryType,\n title: string,\n content: string,\n frontmatter: Record<string, unknown> = {}\n ): Promise<Document> {\n const category = TYPE_TO_CATEGORY[type];\n return this.store({\n category,\n title,\n content,\n frontmatter: { ...frontmatter, memoryType: type }\n });\n }\n\n // === Handoff System ===\n\n /**\n * Create a session handoff document\n * Call this before context death or long pauses\n */\n async createHandoff(handoff: Omit<HandoffDocument, 'created'>): Promise<Document> {\n const now = new Date();\n const dateStr = now.toISOString().split('T')[0];\n const timeStr = now.toISOString().split('T')[1].slice(0, 5).replace(':', '');\n \n const fullHandoff: HandoffDocument = {\n ...handoff,\n created: now.toISOString()\n };\n\n const content = this.formatHandoff(fullHandoff);\n \n // Filter out undefined values to avoid yaml dump errors\n const frontmatter: Record<string, unknown> = {\n type: 'handoff',\n workingOn: handoff.workingOn,\n blocked: handoff.blocked,\n nextSteps: handoff.nextSteps\n };\n if (handoff.sessionKey) frontmatter.sessionKey = handoff.sessionKey;\n if (handoff.feeling) frontmatter.feeling = handoff.feeling;\n if (handoff.decisions) frontmatter.decisions = handoff.decisions;\n if (handoff.openQuestions) frontmatter.openQuestions = handoff.openQuestions;\n \n return this.store({\n category: 'handoffs',\n title: `handoff-${dateStr}-${timeStr}`,\n content,\n frontmatter\n });\n }\n\n /**\n * Format handoff as readable markdown\n */\n private formatHandoff(h: HandoffDocument): string {\n let md = `# Session Handoff\\n\\n`;\n md += `**Created:** ${h.created}\\n`;\n if (h.sessionKey) md += `**Session:** ${h.sessionKey}\\n`;\n if (h.feeling) md += `**Feeling:** ${h.feeling}\\n`;\n md += `\\n`;\n \n md += `## Working On\\n`;\n h.workingOn.forEach(w => md += `- ${w}\\n`);\n md += `\\n`;\n \n md += `## Blocked\\n`;\n if (h.blocked.length === 0) md += `- Nothing currently blocked\\n`;\n else h.blocked.forEach(b => md += `- ${b}\\n`);\n md += `\\n`;\n \n md += `## Next Steps\\n`;\n h.nextSteps.forEach(n => md += `- ${n}\\n`);\n \n if (h.decisions && h.decisions.length > 0) {\n md += `\\n## Decisions Made\\n`;\n h.decisions.forEach(d => md += `- ${d}\\n`);\n }\n \n if (h.openQuestions && h.openQuestions.length > 0) {\n md += `\\n## Open Questions\\n`;\n h.openQuestions.forEach(q => md += `- ${q}\\n`);\n }\n \n return md;\n }\n\n // === Session Recap (Bootstrap Hook) ===\n\n /**\n * Generate a session recap - who I was\n * Call this on bootstrap to restore context\n */\n async generateRecap(options: { handoffLimit?: number; brief?: boolean } = {}): Promise<SessionRecap> {\n const { handoffLimit = 3, brief = false } = options;\n \n // Get recent handoffs\n const handoffDocs = await this.list('handoffs');\n const recentHandoffs = handoffDocs\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())\n .slice(0, handoffLimit)\n .map(doc => this.parseHandoff(doc));\n \n // Get active projects\n const projectDocs = await this.list('projects');\n const activeProjects = projectDocs\n .filter(d => d.frontmatter.status !== 'completed' && d.frontmatter.status !== 'archived')\n .map(d => d.title);\n \n // Get pending commitments\n const commitmentDocs = await this.list('commitments');\n const pendingCommitments = commitmentDocs\n .filter(d => d.frontmatter.status !== 'done')\n .map(d => d.title);\n \n // Get recent decisions (new!)\n const decisionDocs = await this.list('decisions');\n const recentDecisions = decisionDocs\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())\n .slice(0, brief ? 3 : 5)\n .map(d => d.title);\n \n // Get recent lessons\n const lessonDocs = await this.list('lessons');\n const recentLessons = lessonDocs\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())\n .slice(0, brief ? 3 : 5)\n .map(d => d.title);\n \n // Get key relationships (skip in brief mode)\n let keyRelationships: string[] = [];\n if (!brief) {\n const peopleDocs = await this.list('people');\n keyRelationships = peopleDocs\n .filter(d => d.frontmatter.importance === 'high' || d.frontmatter.role)\n .map(d => `${d.title}${d.frontmatter.role ? ` (${d.frontmatter.role})` : ''}`);\n }\n \n // Derive emotional arc from recent handoffs\n const feelings = recentHandoffs\n .map(h => h.feeling)\n .filter(Boolean);\n const emotionalArc = feelings.length > 0 ? feelings.join(' \u2192 ') : undefined;\n \n return {\n generated: new Date().toISOString(),\n recentHandoffs,\n activeProjects,\n pendingCommitments,\n recentDecisions,\n recentLessons,\n keyRelationships,\n emotionalArc\n };\n }\n\n /**\n * Format recap as readable markdown for injection\n */\n formatRecap(recap: SessionRecap, options: { brief?: boolean } = {}): string {\n const { brief = false } = options;\n \n let md = `# Who I Was\\n\\n`;\n md += `*Generated: ${recap.generated}*\\n\\n`;\n \n if (recap.emotionalArc) {\n md += `**Emotional arc:** ${recap.emotionalArc}\\n\\n`;\n }\n \n if (recap.recentHandoffs.length > 0) {\n md += `## Recent Sessions\\n`;\n for (const h of recap.recentHandoffs) {\n if (brief) {\n // Compact format for brief mode\n md += `- **${h.created.split('T')[0]}:** ${h.workingOn.slice(0, 2).join(', ')}`;\n if (h.nextSteps.length > 0) md += ` \u2192 ${h.nextSteps[0]}`;\n md += `\\n`;\n } else {\n md += `\\n### ${h.created.split('T')[0]}\\n`;\n md += `**Working on:** ${h.workingOn.join(', ')}\\n`;\n if (h.blocked.length > 0) md += `**Blocked:** ${h.blocked.join(', ')}\\n`;\n md += `**Next:** ${h.nextSteps.join(', ')}\\n`;\n }\n }\n md += `\\n`;\n }\n \n if (recap.activeProjects.length > 0) {\n md += `## Active Projects\\n`;\n recap.activeProjects.forEach(p => md += `- ${p}\\n`);\n md += `\\n`;\n }\n \n if (recap.pendingCommitments.length > 0) {\n md += `## Pending Commitments\\n`;\n recap.pendingCommitments.forEach(c => md += `- ${c}\\n`);\n md += `\\n`;\n }\n \n if (recap.recentDecisions && recap.recentDecisions.length > 0) {\n md += `## Recent Decisions\\n`;\n recap.recentDecisions.forEach(d => md += `- ${d}\\n`);\n md += `\\n`;\n }\n \n if (recap.recentLessons.length > 0) {\n md += `## Recent Lessons\\n`;\n recap.recentLessons.forEach(l => md += `- ${l}\\n`);\n md += `\\n`;\n }\n \n if (!brief && recap.keyRelationships.length > 0) {\n md += `## Key People\\n`;\n recap.keyRelationships.forEach(r => md += `- ${r}\\n`);\n }\n \n return md;\n }\n\n /**\n * Parse a handoff document back into structured form\n */\n private parseHandoff(doc: Document): HandoffDocument {\n return {\n created: doc.frontmatter.date as string || doc.modified.toISOString(),\n sessionKey: doc.frontmatter.sessionKey as string,\n workingOn: (doc.frontmatter.workingOn as string[]) || [],\n blocked: (doc.frontmatter.blocked as string[]) || [],\n nextSteps: (doc.frontmatter.nextSteps as string[]) || [],\n decisions: doc.frontmatter.decisions as string[] | undefined,\n openQuestions: doc.frontmatter.openQuestions as string[] | undefined,\n feeling: doc.frontmatter.feeling as string\n };\n }\n\n // === Private helpers ===\n\n private applyQmdConfig(meta?: VaultMeta): void {\n const collection = meta?.qmdCollection || this.config.qmdCollection || this.config.name;\n const root = meta?.qmdRoot || this.config.qmdRoot || this.config.path;\n\n this.config.qmdCollection = collection;\n this.config.qmdRoot = root;\n\n this.search.setVaultPath(this.config.path);\n this.search.setCollection(collection);\n this.search.setCollectionRoot(root);\n }\n\n private slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .trim();\n }\n\n private async saveIndex(): Promise<void> {\n const indexPath = path.join(this.config.path, INDEX_FILE);\n const data = this.search.export();\n fs.writeFileSync(indexPath, JSON.stringify(data, null, 2));\n\n // Update config\n const configPath = path.join(this.config.path, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n const meta: VaultMeta = JSON.parse(fs.readFileSync(configPath, 'utf-8'));\n meta.lastUpdated = new Date().toISOString();\n meta.documentCount = this.search.size;\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n }\n }\n\n private async createTemplates(): Promise<void> {\n const templatesPath = path.join(this.config.path, 'templates');\n if (!fs.existsSync(templatesPath)) {\n fs.mkdirSync(templatesPath, { recursive: true });\n }\n\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(moduleDir, '../templates'),\n path.resolve(moduleDir, '../../templates')\n ];\n const builtinDir = candidates.find(dir => fs.existsSync(dir) && fs.statSync(dir).isDirectory());\n if (!builtinDir) return;\n\n for (const entry of fs.readdirSync(builtinDir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith('.md')) continue;\n if (entry.name === 'daily.md') continue;\n const sourcePath = path.join(builtinDir, entry.name);\n const targetPath = path.join(templatesPath, entry.name);\n if (!fs.existsSync(targetPath)) {\n fs.copyFileSync(sourcePath, targetPath);\n }\n }\n }\n\n private generateReadme(): string {\n return `# ${this.config.name} \ud83d\udc18\n\nAn elephant never forgets.\n\n## Structure\n\n${this.config.categories.map(c => `- \\`/${c}/\\` \u2014 ${this.getCategoryDescription(c)}`).join('\\n')}\n\n## Quick Search\n\n\\`\\`\\`bash\nclawvault search \"query\"\n\\`\\`\\`\n\n## Quick Capture\n\n\\`\\`\\`bash\nclawvault store --category inbox --title \"note\" --content \"...\"\n\\`\\`\\`\n\n---\n\n*Managed by [ClawVault](https://github.com/Versatly/clawvault)*\n`;\n }\n\n private getCategoryDescription(category: string): string {\n const descriptions: { [key: string]: string } = {\n // Memory type categories (Benthic's taxonomy)\n facts: 'Raw information, data points, things that are true',\n feelings: 'Emotional states, reactions, energy levels',\n decisions: 'Choices made with context and reasoning',\n lessons: 'What I learned, insights, patterns observed',\n commitments: 'Promises, goals, obligations to fulfill',\n preferences: 'Likes, dislikes, how I want things',\n people: 'Relationships, one file per person',\n projects: 'Active work, ventures, ongoing efforts',\n // System categories\n handoffs: 'Session bridges \u2014 what I was doing, what comes next',\n transcripts: 'Session summaries and logs',\n goals: 'Long-term and short-term objectives',\n patterns: 'Recurring behaviors (\u2192 lessons)',\n inbox: 'Quick capture \u2192 process later',\n templates: 'Templates for each document type'\n };\n return descriptions[category] || category;\n }\n}\n\n/**\n * Find and open the nearest vault (walks up directory tree)\n */\nexport async function findVault(startPath: string = process.cwd()): Promise<ClawVault | null> {\n let current = path.resolve(startPath);\n \n while (current !== path.dirname(current)) {\n const configPath = path.join(current, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n const vault = new ClawVault(current);\n await vault.load();\n return vault;\n }\n current = path.dirname(current);\n }\n \n return null;\n}\n\n/**\n * Create a new vault\n */\nexport async function createVault(vaultPath: string, options: Partial<VaultConfig> = {}): Promise<ClawVault> {\n const vault = new ClawVault(vaultPath);\n await vault.init(options);\n return vault;\n}\n",254 "inputSchema": {},255 "outputSchema": null,256 "icons": null,257 "annotations": null,258 "meta": null,259 "execution": null260 },261 {262 "name": "backlinks.ts",263 "title": null,264 "description": "Script: backlinks.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { buildEntityIndex, type EntityIndex } from './entity-index.js';\n\nconst CLAWVAULT_DIR = '.clawvault';\nconst BACKLINKS_FILE = 'backlinks.json';\nconst WIKI_LINK_REGEX = /\\[\\[([^\\]]+)\\]\\]/g;\n\nexport interface BacklinksScanResult {\n backlinks: Map<string, string[]>;\n orphans: Array<{ source: string; target: string }>;\n linkCount: number;\n}\n\nfunction ensureClawvaultDir(vaultPath: string): string {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\n\nfunction toVaultId(vaultPath: string, filePath: string): string {\n const relative = path.relative(vaultPath, filePath).replace(/\\.md$/, '');\n return relative.split(path.sep).join('/');\n}\n\nfunction normalizeLinkTarget(raw: string): string {\n let target = raw.trim();\n if (!target) return '';\n if (target.startsWith('[[') && target.endsWith(']]')) {\n target = target.slice(2, -2);\n }\n const pipeIndex = target.indexOf('|');\n if (pipeIndex !== -1) {\n target = target.slice(0, pipeIndex);\n }\n if (target.startsWith('#')) return '';\n const hashIndex = target.indexOf('#');\n if (hashIndex !== -1) {\n target = target.slice(0, hashIndex);\n }\n target = target.trim();\n if (!target) return '';\n if (target.endsWith('.md')) {\n target = target.slice(0, -3);\n }\n if (target.startsWith('/')) {\n target = target.slice(1);\n }\n return target.replace(/\\\\/g, '/');\n}\n\nfunction listMarkdownFiles(vaultPath: string): string[] {\n const files: string[] = [];\n const skipDirs = new Set(['archive', 'templates', 'node_modules']);\n\n function walk(dir: string): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name.startsWith('.') || skipDirs.has(entry.name)) continue;\n walk(fullPath);\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n files.push(fullPath);\n }\n }\n }\n\n walk(vaultPath);\n return files;\n}\n\nfunction buildKnownIds(vaultPath: string, files: string[]): {\n ids: Set<string>;\n idsLower: Map<string, string>;\n} {\n const ids = new Set<string>();\n const idsLower = new Map<string, string>();\n\n for (const file of files) {\n const id = toVaultId(vaultPath, file);\n ids.add(id);\n const lower = id.toLowerCase();\n if (!idsLower.has(lower)) {\n idsLower.set(lower, id);\n }\n }\n\n return { ids, idsLower };\n}\n\nfunction resolveTarget(\n target: string,\n known: { ids: Set<string>; idsLower: Map<string, string> },\n entityIndex?: EntityIndex\n): string | null {\n if (!target) return null;\n if (known.ids.has(target)) return target;\n const lower = target.toLowerCase();\n if (known.idsLower.has(lower)) return known.idsLower.get(lower)!;\n if (entityIndex?.entries.has(lower)) return entityIndex.entries.get(lower)!;\n return null;\n}\n\nexport function scanVaultLinks(\n vaultPath: string,\n options: { entityIndex?: EntityIndex } = {}\n): BacklinksScanResult {\n const files = listMarkdownFiles(vaultPath);\n const known = buildKnownIds(vaultPath, files);\n const entityIndex = options.entityIndex ?? buildEntityIndex(vaultPath);\n\n const backlinks = new Map<string, Set<string>>();\n const orphans: Array<{ source: string; target: string }> = [];\n let linkCount = 0;\n\n for (const file of files) {\n const sourceId = toVaultId(vaultPath, file);\n const content = fs.readFileSync(file, 'utf-8');\n const matches = content.match(WIKI_LINK_REGEX) || [];\n linkCount += matches.length;\n\n for (const match of matches) {\n const target = normalizeLinkTarget(match);\n if (!target) continue;\n const resolved = resolveTarget(target, known, entityIndex);\n if (!resolved) {\n orphans.push({ source: sourceId, target });\n continue;\n }\n if (!backlinks.has(resolved)) {\n backlinks.set(resolved, new Set());\n }\n backlinks.get(resolved)!.add(sourceId);\n }\n }\n\n const backlinksMap = new Map<string, string[]>();\n for (const [target, sources] of backlinks) {\n backlinksMap.set(target, [...sources].sort());\n }\n\n return { backlinks: backlinksMap, orphans, linkCount };\n}\n\nexport function writeBacklinksIndex(vaultPath: string, backlinks: Map<string, string[]>): void {\n const dir = ensureClawvaultDir(vaultPath);\n const output: Record<string, string[]> = {};\n\n const targets = [...backlinks.keys()].sort();\n for (const target of targets) {\n const sources = backlinks.get(target) || [];\n output[target] = [...new Set(sources)].sort();\n }\n\n fs.writeFileSync(path.join(dir, BACKLINKS_FILE), JSON.stringify(output, null, 2));\n}\n\nexport function readBacklinksIndex(vaultPath: string): Map<string, string[]> | null {\n const filePath = path.join(vaultPath, CLAWVAULT_DIR, BACKLINKS_FILE);\n if (!fs.existsSync(filePath)) return null;\n try {\n const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, string[]>;\n const map = new Map<string, string[]>();\n for (const [target, sources] of Object.entries(raw)) {\n if (Array.isArray(sources)) {\n map.set(target, sources);\n }\n }\n return map;\n } catch {\n return null;\n }\n}\n\nexport function rebuildBacklinksIndex(\n vaultPath: string,\n options: { entityIndex?: EntityIndex } = {}\n): BacklinksScanResult {\n const result = scanVaultLinks(vaultPath, options);\n writeBacklinksIndex(vaultPath, result.backlinks);\n return result;\n}\n",265 "inputSchema": {},266 "outputSchema": null,267 "icons": null,268 "annotations": null,269 "meta": null,270 "execution": null271 },272 {273 "name": "auto-linker.ts",274 "title": null,275 "description": "Script: auto-linker.ts. Code:\nimport { EntityIndex, getSortedAliases } from './entity-index.js';\n\ninterface ProtectedRange {\n start: number;\n end: number;\n}\n\n/**\n * Find all protected ranges in the content that should not be linked:\n * - Frontmatter (--- blocks)\n * - Code blocks (``` or ~~~)\n * - Inline code (`)\n * - Existing wiki links ([[...]])\n * - URLs\n */\nfunction findProtectedRanges(content: string): ProtectedRange[] {\n const ranges: ProtectedRange[] = [];\n \n // Frontmatter (must be at start)\n const fmMatch = content.match(/^---\\n[\\s\\S]*?\\n---/);\n if (fmMatch) {\n ranges.push({ start: 0, end: fmMatch[0].length });\n }\n \n // Code blocks\n const codeBlockRegex = /```[\\s\\S]*?```|~~~[\\s\\S]*?~~~/g;\n let match;\n while ((match = codeBlockRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n \n // Inline code\n const inlineCodeRegex = /`[^`]+`/g;\n while ((match = inlineCodeRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n \n // Existing wiki links\n const wikiLinkRegex = /\\[\\[[^\\]]+\\]\\]/g;\n while ((match = wikiLinkRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n \n // URLs\n const urlRegex = /https?:\\/\\/[^\\s)>\\]]+/g;\n while ((match = urlRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n \n return ranges;\n}\n\n/**\n * Check if a position is within any protected range\n */\nfunction isProtected(pos: number, ranges: ProtectedRange[]): boolean {\n return ranges.some(r => pos >= r.start && pos < r.end);\n}\n\nfunction createLineLookup(content: string): (pos: number) => number {\n const lines = content.split('\\n');\n let charPos = 0;\n const lineStarts: number[] = [];\n for (const line of lines) {\n lineStarts.push(charPos);\n charPos += line.length + 1;\n }\n\n return (pos: number) => {\n for (let i = lineStarts.length - 1; i >= 0; i--) {\n if (pos >= lineStarts[i]) return i + 1;\n }\n return 1;\n };\n}\n\n/**\n * Auto-link entities in markdown content.\n * Only links first occurrence of each entity.\n * Skips protected ranges (frontmatter, code, existing links, URLs).\n */\nexport function autoLink(content: string, index: EntityIndex): string {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const linkedEntities = new Set<string>();\n \n let result = content;\n let offset = 0; // Track position shifts from replacements\n \n for (const { alias, path } of sortedAliases) {\n // Skip if we already linked this entity\n if (linkedEntities.has(path)) continue;\n \n // Create word-boundary regex (case-insensitive)\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, 'gi');\n \n let match;\n while ((match = regex.exec(content)) !== null) {\n const originalPos = match.index;\n const adjustedPos = originalPos + offset;\n \n // Check if this position is protected in the ORIGINAL content\n if (isProtected(originalPos, protectedRanges)) continue;\n \n // Check if already inside a link in current result\n const beforeMatch = result.substring(0, adjustedPos);\n const openBrackets = (beforeMatch.match(/\\[\\[/g) || []).length;\n const closeBrackets = (beforeMatch.match(/\\]\\]/g) || []).length;\n if (openBrackets > closeBrackets) continue;\n \n // Found a valid match - replace it\n const originalText = match[0];\n const replacement = originalText.toLowerCase() === path.split('/').pop()?.toLowerCase()\n ? `[[${path}]]`\n : `[[${path}|${originalText}]]`;\n \n result = result.substring(0, adjustedPos) + replacement + result.substring(adjustedPos + originalText.length);\n offset += replacement.length - originalText.length;\n \n linkedEntities.add(path);\n break; // Only link first occurrence\n }\n }\n \n return result;\n}\n\n/**\n * Show what would be linked (dry run)\n */\nexport function dryRunLink(content: string, index: EntityIndex): Array<{ alias: string; path: string; line: number }> {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const linkedEntities = new Set<string>();\n const matches: Array<{ alias: string; path: string; line: number }> = [];\n const getLineNumber = createLineLookup(content);\n \n for (const { alias, path } of sortedAliases) {\n if (linkedEntities.has(path)) continue;\n \n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, 'gi');\n \n let match;\n while ((match = regex.exec(content)) !== null) {\n if (isProtected(match.index, protectedRanges)) continue;\n \n matches.push({\n alias: match[0],\n path,\n line: getLineNumber(match.index)\n });\n linkedEntities.add(path);\n break;\n }\n }\n \n return matches;\n}\n\n/**\n * Find unlinked mentions of entities (suggested links).\n */\nexport function findUnlinkedMentions(\n content: string,\n index: EntityIndex\n): Array<{ alias: string; path: string; line: number }> {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const matches: Array<{ alias: string; path: string; line: number }> = [];\n const seen = new Set<string>();\n const getLineNumber = createLineLookup(content);\n\n for (const { alias, path } of sortedAliases) {\n if (seen.has(path)) continue;\n\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, 'gi');\n\n let match;\n while ((match = regex.exec(content)) !== null) {\n if (isProtected(match.index, protectedRanges)) continue;\n\n matches.push({\n alias: match[0],\n path,\n line: getLineNumber(match.index)\n });\n seen.add(path);\n break;\n }\n }\n\n return matches;\n}\n",276 "inputSchema": {},277 "outputSchema": null,278 "icons": null,279 "annotations": null,280 "meta": null,281 "execution": null282 },283 {284 "name": "session-repair.ts",285 "title": null,286 "description": "Script: session-repair.ts. Code:\n/**\n * Session transcript repair logic\n * \n * Repairs corrupted OpenClaw session transcripts by:\n * 1. Finding aborted tool_use blocks (stopReason: \"aborted\", partialJson present)\n * 2. Finding orphaned tool_result messages that reference non-existent tool_use IDs\n * 3. Removing both the aborted entries and orphaned results\n * 4. Relinking parent chain references\n */\n\nimport * as fs from 'fs';\n\nexport interface TranscriptEntry {\n type: 'session' | 'message' | 'compaction' | 'custom' | 'thinking_level_change' | string;\n id: string;\n parentId: string | null;\n timestamp: string;\n message?: {\n role: 'user' | 'assistant' | 'toolResult' | 'system';\n content: Array<{\n type: string;\n id?: string;\n name?: string;\n arguments?: unknown;\n toolCallId?: string;\n toolUseId?: string;\n partialJson?: string;\n text?: string;\n }>;\n stopReason?: string;\n errorMessage?: string;\n };\n summary?: string;\n customType?: string;\n data?: unknown;\n thinkingLevel?: string;\n}\n\nexport interface ToolUseInfo {\n id: string;\n lineNumber: number;\n entryId: string;\n isAborted: boolean;\n isPartial: boolean;\n name?: string;\n}\n\nexport interface CorruptedEntry {\n lineNumber: number;\n entryId: string;\n type: 'aborted_tool_use' | 'orphaned_tool_result';\n toolUseId: string;\n description: string;\n}\n\nexport interface ParentRelink {\n lineNumber: number;\n entryId: string;\n oldParentId: string;\n newParentId: string;\n}\n\nexport interface RepairResult {\n sessionId: string;\n totalLines: number;\n corruptedEntries: CorruptedEntry[];\n parentRelinks: ParentRelink[];\n removedCount: number;\n relinkedCount: number;\n backupPath?: string;\n repaired: boolean;\n}\n\n/**\n * Parse a JSONL file into transcript entries with line numbers\n */\nexport function parseTranscript(filePath: string): Array<{ line: number; entry: TranscriptEntry; raw: string }> {\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n \n const entries: Array<{ line: number; entry: TranscriptEntry; raw: string }> = [];\n \n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i];\n try {\n const entry = JSON.parse(raw) as TranscriptEntry;\n entries.push({ line: i + 1, entry, raw });\n } catch {\n // Skip malformed lines\n console.warn(`Warning: Could not parse line ${i + 1}`);\n }\n }\n \n return entries;\n}\n\n/**\n * Extract all tool_use IDs from assistant messages\n */\nexport function extractToolUses(\n entries: Array<{ line: number; entry: TranscriptEntry }>\n): Map<string, ToolUseInfo> {\n const toolUses = new Map<string, ToolUseInfo>();\n \n for (const { line, entry } of entries) {\n if (entry.type !== 'message') continue;\n if (entry.message?.role !== 'assistant') continue;\n \n const isAborted = entry.message.stopReason === 'aborted';\n const content = entry.message.content || [];\n \n for (const block of content) {\n // Check for various tool call block types\n if (block.type === 'toolCall' || block.type === 'tool_use' || block.type === 'functionCall') {\n if (block.id) {\n const isPartial = !!block.partialJson;\n toolUses.set(block.id, {\n id: block.id,\n lineNumber: line,\n entryId: entry.id,\n isAborted: isAborted || isPartial,\n isPartial,\n name: block.name\n });\n }\n }\n }\n }\n \n return toolUses;\n}\n\n/**\n * Find orphaned tool_result messages that reference non-existent or aborted tool_use IDs\n */\nexport function findCorruptedEntries(\n entries: Array<{ line: number; entry: TranscriptEntry }>,\n toolUses: Map<string, ToolUseInfo>\n): {\n corrupted: CorruptedEntry[];\n entriesToRemove: Set<string>;\n} {\n const corrupted: CorruptedEntry[] = [];\n const entriesToRemove = new Set<string>();\n \n // First, mark aborted tool_uses for removal\n for (const [toolId, info] of toolUses) {\n if (info.isAborted) {\n corrupted.push({\n lineNumber: info.lineNumber,\n entryId: info.entryId,\n type: 'aborted_tool_use',\n toolUseId: toolId,\n description: `Aborted tool_use${info.name ? ` (${info.name})` : ''} with id: ${toolId}`\n });\n entriesToRemove.add(info.entryId);\n }\n }\n \n // Find orphaned tool_results\n for (const { line, entry } of entries) {\n if (entry.type !== 'message') continue;\n if (entry.message?.role !== 'toolResult') continue;\n \n // Get the tool_use ID this result references\n const content = entry.message.content || [];\n let toolCallId: string | undefined;\n \n // Check the message-level toolCallId (common pattern)\n const msg = entry.message as { toolCallId?: string; toolUseId?: string };\n toolCallId = msg.toolCallId || msg.toolUseId;\n \n // Also check content blocks for toolCallId\n if (!toolCallId) {\n for (const block of content) {\n if (block.toolCallId || block.toolUseId) {\n toolCallId = block.toolCallId || block.toolUseId;\n break;\n }\n }\n }\n \n if (!toolCallId) continue;\n \n // Check if the referenced tool_use exists and is valid\n const toolUse = toolUses.get(toolCallId);\n \n if (!toolUse || toolUse.isAborted) {\n corrupted.push({\n lineNumber: line,\n entryId: entry.id,\n type: 'orphaned_tool_result',\n toolUseId: toolCallId,\n description: toolUse\n ? `Orphaned tool_result references aborted tool_use: ${toolCallId}`\n : `Orphaned tool_result references non-existent tool_use: ${toolCallId}`\n });\n entriesToRemove.add(entry.id);\n }\n }\n \n return { corrupted, entriesToRemove };\n}\n\n/**\n * Compute parent chain relinks after removing entries\n */\nexport function computeParentRelinks(\n entries: Array<{ line: number; entry: TranscriptEntry }>,\n entriesToRemove: Set<string>\n): ParentRelink[] {\n const relinks: ParentRelink[] = [];\n \n // Build a map of entry ID to its parent ID\n const entryParents = new Map<string, string | null>();\n for (const { entry } of entries) {\n entryParents.set(entry.id, entry.parentId);\n }\n \n // For each entry that references a removed entry as parent, find the next valid ancestor\n for (const { line, entry } of entries) {\n if (entriesToRemove.has(entry.id)) continue; // Skip entries being removed\n if (!entry.parentId) continue;\n if (!entriesToRemove.has(entry.parentId)) continue; // Parent is valid\n \n // Find the next valid ancestor\n let newParentId: string | null = entry.parentId;\n while (newParentId && entriesToRemove.has(newParentId)) {\n newParentId = entryParents.get(newParentId) || null;\n }\n \n if (newParentId !== entry.parentId) {\n relinks.push({\n lineNumber: line,\n entryId: entry.id,\n oldParentId: entry.parentId,\n newParentId: newParentId || 'null'\n });\n }\n }\n \n return relinks;\n}\n\n/**\n * Analyze a session transcript for corruption without modifying it\n */\nexport function analyzeSession(filePath: string): RepairResult {\n const entries = parseTranscript(filePath);\n \n // Extract session ID from first entry\n const sessionEntry = entries.find(e => e.entry.type === 'session');\n const sessionId = sessionEntry?.entry.id || 'unknown';\n \n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const parentRelinks = computeParentRelinks(entries, entriesToRemove);\n \n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n repaired: false\n };\n}\n\n/**\n * Repair a session transcript\n */\nexport function repairSession(\n filePath: string,\n options: { backup?: boolean; dryRun?: boolean } = {}\n): RepairResult {\n const { backup = true, dryRun = false } = options;\n \n const entries = parseTranscript(filePath);\n \n // Extract session ID from first entry\n const sessionEntry = entries.find(e => e.entry.type === 'session');\n const sessionId = sessionEntry?.entry.id || 'unknown';\n \n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const parentRelinks = computeParentRelinks(entries, entriesToRemove);\n \n if (corrupted.length === 0) {\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: [],\n parentRelinks: [],\n removedCount: 0,\n relinkedCount: 0,\n repaired: false\n };\n }\n \n if (dryRun) {\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n repaired: false\n };\n }\n \n // Create backup if requested\n let backupPath: string | undefined;\n if (backup) {\n const timestamp = new Date().toISOString()\n .replace(/[:.]/g, '')\n .replace('T', '-')\n .slice(0, 15);\n backupPath = `${filePath}.backup-${timestamp}`;\n fs.copyFileSync(filePath, backupPath);\n }\n \n // Build relink map for quick lookup\n const relinkMap = new Map<string, string | null>();\n for (const relink of parentRelinks) {\n relinkMap.set(relink.entryId, relink.newParentId === 'null' ? null : relink.newParentId);\n }\n \n // Write repaired transcript\n const repairedLines: string[] = [];\n \n for (const { entry, raw } of entries) {\n // Skip removed entries\n if (entriesToRemove.has(entry.id)) continue;\n \n // Apply relinks if needed\n if (relinkMap.has(entry.id)) {\n const newEntry = { ...entry, parentId: relinkMap.get(entry.id) };\n repairedLines.push(JSON.stringify(newEntry));\n } else {\n repairedLines.push(raw);\n }\n }\n \n fs.writeFileSync(filePath, repairedLines.join('\\n') + '\\n');\n \n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n backupPath,\n repaired: true\n };\n}\n",287 "inputSchema": {},288 "outputSchema": null,289 "icons": null,290 "annotations": null,291 "meta": null,292 "execution": null293 },294 {295 "name": "template-engine.test.ts",296 "title": null,297 "description": "Script: template-engine.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport { buildTemplateVariables, renderTemplate } from './template-engine.js';\n\nafterEach(() => {\n vi.useRealTimers();\n});\n\ndescribe('template engine', () => {\n it('interpolates variables in frontmatter and body', () => {\n vi.useFakeTimers();\n vi.setSystemTime(new Date('2026-02-03T10:11:12Z'));\n\n const vars = buildTemplateVariables({ title: 'Alpha', type: 'decision' });\n const template = `---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\n---\n# {{title}}\n{{datetime}}\n`;\n\n const output = renderTemplate(template, vars);\n expect(output).toContain('title: \"Alpha\"');\n expect(output).toContain('date: 2026-02-03');\n expect(output).toContain('type: decision');\n expect(output).toContain('2026-02-03T10:11:12.000Z');\n });\n\n it('leaves unknown tokens untouched', () => {\n const vars = buildTemplateVariables({ title: 'Alpha', type: 'note' }, new Date('2026-02-03T00:00:00Z'));\n const output = renderTemplate('Hello {{unknown}}', vars);\n expect(output).toBe('Hello {{unknown}}');\n });\n});\n",298 "inputSchema": {},299 "outputSchema": null,300 "icons": null,301 "annotations": null,302 "meta": null,303 "execution": null304 },305 {306 "name": "session-utils.ts",307 "title": null,308 "description": "Script: session-utils.ts. Code:\n/**\n * Session discovery utilities for OpenClaw transcripts\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nexport interface SessionInfo {\n sessionId: string;\n sessionKey: string;\n agentId: string;\n filePath: string;\n updatedAt?: number;\n}\n\nexport interface SessionsStore {\n [sessionKey: string]: {\n sessionId: string;\n updatedAt?: number;\n [key: string]: unknown;\n };\n}\n\n/**\n * Get the OpenClaw agents directory\n */\nexport function getOpenClawAgentsDir(): string {\n return path.join(os.homedir(), '.openclaw', 'agents');\n}\n\n/**\n * Get the sessions directory for an agent\n */\nexport function getSessionsDir(agentId: string): string {\n return path.join(getOpenClawAgentsDir(), agentId, 'sessions');\n}\n\n/**\n * Get the path to sessions.json for an agent\n */\nexport function getSessionsJsonPath(agentId: string): string {\n return path.join(getSessionsDir(agentId), 'sessions.json');\n}\n\n/**\n * Get the path to a session JSONL file\n */\nexport function getSessionFilePath(agentId: string, sessionId: string): string {\n return path.join(getSessionsDir(agentId), `${sessionId}.jsonl`);\n}\n\n/**\n * List all available agents\n */\nexport function listAgents(): string[] {\n const agentsDir = getOpenClawAgentsDir();\n if (!fs.existsSync(agentsDir)) {\n return [];\n }\n \n return fs.readdirSync(agentsDir)\n .filter(name => {\n const sessionsDir = getSessionsDir(name);\n return fs.existsSync(sessionsDir) && fs.statSync(sessionsDir).isDirectory();\n });\n}\n\n/**\n * Load sessions.json for an agent\n */\nexport function loadSessionsStore(agentId: string): SessionsStore | null {\n const sessionsJsonPath = getSessionsJsonPath(agentId);\n if (!fs.existsSync(sessionsJsonPath)) {\n return null;\n }\n \n try {\n const content = fs.readFileSync(sessionsJsonPath, 'utf-8');\n return JSON.parse(content) as SessionsStore;\n } catch {\n return null;\n }\n}\n\n/**\n * Find the current/main session for an agent\n */\nexport function findMainSession(agentId: string): SessionInfo | null {\n const store = loadSessionsStore(agentId);\n if (!store) return null;\n \n // Look for the main session key pattern\n const mainKey = `agent:${agentId}:main`;\n const entry = store[mainKey];\n \n if (entry?.sessionId) {\n const filePath = getSessionFilePath(agentId, entry.sessionId);\n if (fs.existsSync(filePath)) {\n return {\n sessionId: entry.sessionId,\n sessionKey: mainKey,\n agentId,\n filePath,\n updatedAt: entry.updatedAt\n };\n }\n }\n \n return null;\n}\n\n/**\n * Find a session by ID\n */\nexport function findSessionById(agentId: string, sessionId: string): SessionInfo | null {\n const filePath = getSessionFilePath(agentId, sessionId);\n if (!fs.existsSync(filePath)) {\n return null;\n }\n \n const store = loadSessionsStore(agentId);\n let sessionKey: string | undefined;\n let updatedAt: number | undefined;\n \n if (store) {\n for (const [key, entry] of Object.entries(store)) {\n if (entry.sessionId === sessionId) {\n sessionKey = key;\n updatedAt = entry.updatedAt;\n break;\n }\n }\n }\n \n return {\n sessionId,\n sessionKey: sessionKey || `agent:${agentId}:unknown`,\n agentId,\n filePath,\n updatedAt\n };\n}\n\n/**\n * List all sessions for an agent\n */\nexport function listSessions(agentId: string): SessionInfo[] {\n const sessionsDir = getSessionsDir(agentId);\n if (!fs.existsSync(sessionsDir)) {\n return [];\n }\n \n const store = loadSessionsStore(agentId);\n const sessions: SessionInfo[] = [];\n \n const files = fs.readdirSync(sessionsDir)\n .filter(f => f.endsWith('.jsonl') && !f.includes('.backup') && !f.includes('.deleted') && !f.includes('.corrupted'));\n \n for (const file of files) {\n const sessionId = file.replace('.jsonl', '');\n const filePath = path.join(sessionsDir, file);\n \n let sessionKey = `agent:${agentId}:unknown`;\n let updatedAt: number | undefined;\n \n if (store) {\n for (const [key, entry] of Object.entries(store)) {\n if (entry.sessionId === sessionId) {\n sessionKey = key;\n updatedAt = entry.updatedAt;\n break;\n }\n }\n }\n \n sessions.push({\n sessionId,\n sessionKey,\n agentId,\n filePath,\n updatedAt\n });\n }\n \n return sessions.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n}\n\n/**\n * Create a backup of a session file\n */\nexport function backupSession(filePath: string): string {\n const timestamp = new Date().toISOString()\n .replace(/[:.]/g, '')\n .replace('T', '-')\n .slice(0, 15);\n \n const backupPath = `${filePath}.backup-${timestamp}`;\n fs.copyFileSync(filePath, backupPath);\n return backupPath;\n}\n",309 "inputSchema": {},310 "outputSchema": null,311 "icons": null,312 "annotations": null,313 "meta": null,314 "execution": null315 },316 {317 "name": "template-engine.ts",318 "title": null,319 "description": "Script: template-engine.ts. Code:\nexport interface TemplateVariables {\n title: string;\n date: string;\n datetime: string;\n type: string;\n}\n\nexport function buildTemplateVariables(\n input: Partial<TemplateVariables> = {},\n now: Date = new Date()\n): TemplateVariables {\n const datetime = input.datetime ?? now.toISOString();\n const date = input.date ?? datetime.split('T')[0];\n\n return {\n title: input.title ?? '',\n type: input.type ?? '',\n date,\n datetime\n };\n}\n\nexport function renderTemplate(template: string, variables: TemplateVariables): string {\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_-]+)\\s*\\}\\}/g, (match, key) => {\n const value = variables[key as keyof TemplateVariables];\n return value !== undefined ? String(value) : match;\n });\n}\n",320 "inputSchema": {},321 "outputSchema": null,322 "icons": null,323 "annotations": null,324 "meta": null,325 "execution": null326 },327 {328 "name": "time.ts",329 "title": null,330 "description": "Script: time.ts. Code:\nexport function formatAge(ms: number): string {\n if (!Number.isFinite(ms)) return 'unknown';\n const seconds = Math.max(0, Math.floor(ms / 1000));\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d ${hours % 24}h`;\n if (hours > 0) return `${hours}h ${minutes % 60}m`;\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\n}\n",331 "inputSchema": {},332 "outputSchema": null,333 "icons": null,334 "annotations": null,335 "meta": null,336 "execution": null337 },338 {339 "name": "backlinks.test.ts",340 "title": null,341 "description": "Script: backlinks.test.ts. Code:\nimport { afterEach, describe, expect, it } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { readBacklinksIndex, scanVaultLinks, writeBacklinksIndex } from './backlinks.js';\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-backlinks-'));\n}\n\nfunction writeFile(root: string, relative: string, content: string): void {\n const filePath = path.join(root, relative);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, content);\n}\n\ndescribe('backlinks scan', () => {\n it('builds backlinks and orphans', () => {\n const vaultPath = makeTempVaultDir();\n try {\n writeFile(vaultPath, 'people/alice.md', '# Alice');\n writeFile(vaultPath, 'projects/proj-x.md', '# Project X');\n writeFile(\n vaultPath,\n 'notes/a.md',\n 'Meeting with [[people/alice]] about [[projects/proj-x|Project X]].'\n );\n writeFile(vaultPath, 'notes/b.md', 'Follow up with [[people/alice]] and [[unknown]].');\n\n const result = scanVaultLinks(vaultPath);\n expect(result.linkCount).toBe(4);\n expect(result.backlinks.get('people/alice')).toEqual(['notes/a', 'notes/b']);\n expect(result.backlinks.get('projects/proj-x')).toEqual(['notes/a']);\n expect(result.orphans).toEqual([{ source: 'notes/b', target: 'unknown' }]);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('writes and reads backlinks index', () => {\n const vaultPath = makeTempVaultDir();\n try {\n writeFile(vaultPath, 'people/alice.md', '# Alice');\n writeFile(vaultPath, 'notes/a.md', 'See [[people/alice]].');\n\n const result = scanVaultLinks(vaultPath);\n writeBacklinksIndex(vaultPath, result.backlinks);\n\n const loaded = readBacklinksIndex(vaultPath);\n expect(loaded).not.toBeNull();\n expect(loaded?.get('people/alice')).toEqual(['notes/a']);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n});\n",342 "inputSchema": {},343 "outputSchema": null,344 "icons": null,345 "annotations": null,346 "meta": null,347 "execution": null348 },349 {350 "name": "template.test.ts",351 "title": null,352 "description": "Script: template.test.ts. Code:\nimport { afterEach, describe, expect, it } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { addTemplate, createFromTemplate, listTemplates } from './template.js';\n\nconst tempDirs: string[] = [];\n\nfunction makeTempDir(prefix: string): string {\n const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));\n tempDirs.push(dir);\n return dir;\n}\n\nafterEach(() => {\n while (tempDirs.length > 0) {\n const dir = tempDirs.pop();\n if (dir) {\n fs.rmSync(dir, { recursive: true, force: true });\n }\n }\n});\n\ndescribe('template command', () => {\n it('lists templates and creates a file from a custom template', () => {\n const vaultDir = makeTempDir('clawvault-template-vault-');\n const templatesDir = path.join(vaultDir, 'templates');\n fs.mkdirSync(templatesDir, { recursive: true });\n fs.writeFileSync(\n path.join(templatesDir, 'custom.md'),\n `---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\n---\n# {{title}}\n`\n );\n\n const builtinDir = makeTempDir('clawvault-template-builtin-');\n fs.writeFileSync(path.join(builtinDir, 'builtin.md'), '# Builtin');\n\n const names = listTemplates({ vaultPath: vaultDir, builtinDir });\n expect(names).toEqual(expect.arrayContaining(['custom', 'builtin']));\n\n const outputDir = makeTempDir('clawvault-template-out-');\n const result = createFromTemplate('custom', {\n vaultPath: vaultDir,\n builtinDir,\n cwd: outputDir,\n title: 'Alpha Plan',\n type: 'custom'\n });\n\n expect(result.outputPath).toBe(path.join(outputDir, 'alpha-plan.md'));\n const content = fs.readFileSync(result.outputPath, 'utf-8');\n expect(content).toContain('Alpha Plan');\n expect(content).not.toContain('{{title}}');\n });\n\n it('adds a template to the vault templates folder', () => {\n const vaultDir = makeTempDir('clawvault-template-vault-');\n const sourceDir = makeTempDir('clawvault-template-src-');\n const sourcePath = path.join(sourceDir, 'source.md');\n fs.writeFileSync(sourcePath, '# Custom Template');\n\n const result = addTemplate(sourcePath, { vaultPath: vaultDir, name: 'added' });\n const saved = fs.readFileSync(result.templatePath, 'utf-8');\n expect(saved).toBe('# Custom Template');\n });\n});\n",353 "inputSchema": {},354 "outputSchema": null,355 "icons": null,356 "annotations": null,357 "meta": null,358 "execution": null359 },360 {361 "name": "checkpoint.ts",362 "title": null,363 "description": "Script: checkpoint.ts. Code:\n/**\n * Quick checkpoint command - fast state save for context death resilience\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { execFileSync } from 'child_process';\n\nexport interface CheckpointOptions {\n workingOn?: string;\n focus?: string;\n blocked?: string;\n vaultPath: string;\n urgent?: boolean;\n}\n\nexport interface CheckpointData {\n timestamp: string;\n workingOn: string | null;\n focus: string | null;\n blocked: string | null;\n sessionId?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n sessionStartedAt?: string;\n urgent?: boolean;\n}\n\nexport interface SessionState {\n sessionId?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n startedAt?: string;\n}\n\nconst CLAWVAULT_DIR = '.clawvault';\nconst CHECKPOINT_FILE = 'last-checkpoint.json';\nconst SESSION_STATE_FILE = 'session-state.json';\nconst DIRTY_DEATH_FLAG = 'dirty-death.flag';\n\nlet pendingCheckpoint: NodeJS.Timeout | null = null;\nlet pendingData: { dir: string; data: CheckpointData } | null = null;\n\nfunction ensureClawvaultDir(vaultPath: string): string {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\n\nfunction writeCheckpointToDisk(dir: string, data: CheckpointData): void {\n const checkpointPath = path.join(dir, CHECKPOINT_FILE);\n fs.writeFileSync(checkpointPath, JSON.stringify(data, null, 2));\n\n const flagPath = path.join(dir, DIRTY_DEATH_FLAG);\n fs.writeFileSync(flagPath, data.timestamp);\n}\n\nfunction parseTokenEstimate(raw?: string): number | undefined {\n if (!raw) return undefined;\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction loadSessionState(dir: string): SessionState | null {\n const sessionStatePath = path.join(dir, SESSION_STATE_FILE);\n if (!fs.existsSync(sessionStatePath)) return null;\n try {\n return JSON.parse(fs.readFileSync(sessionStatePath, 'utf-8')) as SessionState;\n } catch {\n return null;\n }\n}\n\nfunction getEnvSessionState(): SessionState {\n return {\n sessionKey: process.env.OPENCLAW_SESSION_KEY,\n model: process.env.OPENCLAW_MODEL,\n tokenEstimate: parseTokenEstimate(\n process.env.OPENCLAW_TOKEN_ESTIMATE || process.env.OPENCLAW_CONTEXT_TOKENS\n )\n };\n}\n\nfunction triggerUrgentWake(data: CheckpointData): void {\n const summary = [\n data.workingOn ? `Working on: ${data.workingOn}` : null,\n data.focus ? `Focus: ${data.focus}` : null,\n data.blocked ? `Blocked: ${data.blocked}` : null\n ].filter(Boolean).join(' | ');\n\n const text = summary\n ? `Urgent checkpoint saved. ${summary}`\n : 'Urgent checkpoint saved.';\n\n try {\n execFileSync('openclaw', ['gateway', 'wake', '--text', text, '--mode', 'now'], {\n stdio: 'inherit'\n });\n } catch (err: any) {\n if (err?.code === 'ENOENT') {\n throw new Error('Urgent wake failed: openclaw CLI not found.');\n }\n throw new Error(`Urgent wake failed: ${err?.message || 'unknown error'}`);\n }\n}\n\nexport async function flush(): Promise<CheckpointData | null> {\n if (pendingCheckpoint) {\n clearTimeout(pendingCheckpoint);\n pendingCheckpoint = null;\n }\n if (!pendingData) return null;\n\n const { dir, data } = pendingData;\n pendingData = null;\n writeCheckpointToDisk(dir, data);\n return data;\n}\n\nexport async function checkpoint(options: CheckpointOptions): Promise<CheckpointData> {\n const dir = ensureClawvaultDir(options.vaultPath);\n \n const data: CheckpointData = {\n timestamp: new Date().toISOString(),\n workingOn: options.workingOn || null,\n focus: options.focus || null,\n blocked: options.blocked || null,\n urgent: options.urgent || false\n };\n \n const sessionState = loadSessionState(dir);\n const envState = getEnvSessionState();\n data.sessionId = sessionState?.sessionId;\n data.sessionKey = envState.sessionKey || sessionState?.sessionKey || sessionState?.sessionId;\n data.model = envState.model || sessionState?.model;\n data.tokenEstimate = envState.tokenEstimate ?? sessionState?.tokenEstimate;\n data.sessionStartedAt = sessionState?.startedAt;\n\n if (options.urgent) {\n if (pendingCheckpoint) {\n clearTimeout(pendingCheckpoint);\n pendingCheckpoint = null;\n }\n pendingData = null;\n writeCheckpointToDisk(dir, data);\n triggerUrgentWake(data);\n } else {\n // Debounce writes to avoid rapid write spam; last call wins.\n pendingData = { dir, data };\n if (pendingCheckpoint) clearTimeout(pendingCheckpoint);\n pendingCheckpoint = setTimeout(() => {\n void flush();\n }, 1000);\n }\n\n return data;\n}\n\nexport async function clearDirtyFlag(vaultPath: string): Promise<void> {\n const flagPath = path.join(vaultPath, CLAWVAULT_DIR, DIRTY_DEATH_FLAG);\n if (fs.existsSync(flagPath)) {\n fs.unlinkSync(flagPath);\n }\n}\n\n// Alias for CLI ergonomics (`clawvault clean-exit`)\nexport async function cleanExit(vaultPath: string): Promise<void> {\n await clearDirtyFlag(vaultPath);\n}\n\nexport async function checkDirtyDeath(vaultPath: string): Promise<{\n died: boolean;\n checkpoint: CheckpointData | null;\n deathTime: string | null;\n}> {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n const flagPath = path.join(dir, DIRTY_DEATH_FLAG);\n const checkpointPath = path.join(dir, CHECKPOINT_FILE);\n \n if (!fs.existsSync(flagPath)) {\n return { died: false, checkpoint: null, deathTime: null };\n }\n \n const deathTime = fs.readFileSync(flagPath, 'utf-8').trim();\n \n let checkpoint: CheckpointData | null = null;\n if (fs.existsSync(checkpointPath)) {\n try {\n checkpoint = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));\n } catch {\n // Ignore parse errors\n }\n }\n \n return { died: true, checkpoint, deathTime };\n}\n\nexport async function setSessionState(vaultPath: string, session: string | SessionState): Promise<void> {\n const dir = ensureClawvaultDir(vaultPath);\n const sessionStatePath = path.join(dir, SESSION_STATE_FILE);\n \n const state: SessionState = typeof session === 'string'\n ? { sessionId: session }\n : { ...session };\n\n if (!state.startedAt) {\n state.startedAt = new Date().toISOString();\n }\n\n fs.writeFileSync(sessionStatePath, JSON.stringify(state, null, 2));\n}\n",364 "inputSchema": {},365 "outputSchema": null,366 "icons": null,367 "annotations": null,368 "meta": null,369 "execution": null370 },371 {372 "name": "doctor.ts",373 "title": null,374 "description": "Script: doctor.ts. Code:\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { ClawVault, findVault } from '../lib/vault.js';\nimport { scanVaultLinks } from '../lib/backlinks.js';\nimport { formatAge } from '../lib/time.js';\nimport { hasQmd } from '../lib/search.js';\n\nconst CLAWVAULT_DIR = '.clawvault';\nconst CHECKPOINT_FILE = 'last-checkpoint.json';\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst ACTIVE_USE_DAYS = 7;\n\nexport type DoctorStatus = 'ok' | 'warn' | 'error';\n\nexport interface DoctorCheck {\n label: string;\n status: DoctorStatus;\n detail?: string;\n hint?: string;\n}\n\nexport interface DoctorReport {\n vaultPath?: string;\n checks: DoctorCheck[];\n warnings: number;\n errors: number;\n}\n\nfunction daysSince(date: Date, now: number = Date.now()): number {\n return Math.max(0, Math.floor((now - date.getTime()) / DAY_MS));\n}\n\nfunction describeAge(date: Date, now: number = Date.now()): string {\n return formatAge(now - date.getTime());\n}\n\nfunction loadCheckpointTimestamp(vaultPath: string): { timestamp?: string; error?: string } {\n const checkpointPath = path.join(vaultPath, CLAWVAULT_DIR, CHECKPOINT_FILE);\n if (!fs.existsSync(checkpointPath)) {\n return {};\n }\n try {\n const data = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8')) as { timestamp?: string };\n return { timestamp: data.timestamp };\n } catch (err: any) {\n return { error: err?.message || 'Failed to parse checkpoint' };\n }\n}\n\nfunction getShellConfigPaths(shellPath: string | undefined): string[] {\n const home = os.homedir();\n const shellName = shellPath ? path.basename(shellPath) : 'bash';\n if (shellName === 'zsh') {\n return [path.join(home, '.zshrc'), path.join(home, '.zprofile')];\n }\n if (shellName === 'fish') {\n return [path.join(home, '.config', 'fish', 'config.fish')];\n }\n return [path.join(home, '.bashrc'), path.join(home, '.bash_profile'), path.join(home, '.profile')];\n}\n\nfunction hasClawvaultPathConfig(paths: string[]): boolean {\n for (const filePath of paths) {\n if (!fs.existsSync(filePath)) continue;\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n if (/CLAWVAULT_PATH\\s*=/.test(content)) {\n return true;\n }\n } catch {\n // ignore unreadable config files\n }\n }\n return false;\n}\n\nasync function resolveVault(vaultPath?: string): Promise<ClawVault> {\n if (vaultPath) {\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n return vault;\n }\n\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n const vault = new ClawVault(path.resolve(envPath));\n await vault.load();\n return vault;\n }\n\n const found = await findVault();\n if (!found) {\n throw new Error('No ClawVault found. Run `clawvault init` first.');\n }\n return found;\n}\n\nexport async function doctor(vaultPath?: string): Promise<DoctorReport> {\n const checks: DoctorCheck[] = [];\n let warnings = 0;\n let errors = 0;\n\n if (hasQmd()) {\n checks.push({ label: 'qmd installed', status: 'ok' });\n } else {\n checks.push({\n label: 'qmd installed',\n status: 'error',\n hint: 'Install qmd to enable ClawVault commands.'\n });\n errors++;\n }\n\n const shellConfigs = getShellConfigPaths(process.env.SHELL).filter(fs.existsSync);\n if (hasClawvaultPathConfig(shellConfigs)) {\n checks.push({\n label: 'CLAWVAULT_PATH in shell config',\n status: 'ok',\n detail: shellConfigs.map(p => path.basename(p)).join(', ')\n });\n } else {\n checks.push({\n label: 'CLAWVAULT_PATH in shell config',\n status: 'warn',\n hint: 'Run `clawvault shell-init` and add it to your shell rc.'\n });\n warnings++;\n }\n\n if (!hasQmd()) {\n return { vaultPath, checks, warnings, errors };\n }\n\n let vault: ClawVault;\n try {\n vault = await resolveVault(vaultPath);\n checks.push({ label: 'vault found', status: 'ok', detail: vault.getPath() });\n } catch (err: any) {\n checks.push({\n label: 'vault found',\n status: 'error',\n detail: err?.message || 'Unable to locate vault'\n });\n errors++;\n return { vaultPath, checks, warnings, errors };\n }\n\n const stats = await vault.stats();\n const documents = await vault.list();\n const handoffs = await vault.list('handoffs');\n const inbox = await vault.list('inbox');\n const qmdCollection = vault.getQmdCollection();\n\n if (qmdCollection) {\n checks.push({ label: 'qmd collection configured', status: 'ok', detail: qmdCollection });\n } else {\n checks.push({\n label: 'qmd collection configured',\n status: 'warn',\n hint: 'Set qmd collection in .clawvault.json'\n });\n warnings++;\n }\n\n const latestDoc = documents\n .slice()\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())[0];\n const latestDocAge = latestDoc ? daysSince(latestDoc.modified) : null;\n\n let lastHandoffAge: number | null = null;\n if (handoffs.length === 0) {\n checks.push({\n label: 'recent handoff',\n status: 'warn',\n hint: 'Run `clawvault sleep` at the end of sessions.'\n });\n warnings++;\n } else {\n const latestHandoff = handoffs\n .slice()\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())[0];\n lastHandoffAge = daysSince(latestHandoff.modified);\n const ageLabel = describeAge(latestHandoff.modified);\n if (lastHandoffAge > 1) {\n checks.push({\n label: 'recent handoff',\n status: 'warn',\n detail: `Last handoff ${ageLabel} ago`,\n hint: 'Run `clawvault sleep` before long pauses.'\n });\n warnings++;\n } else {\n checks.push({\n label: 'recent handoff',\n status: 'ok',\n detail: `Last handoff ${ageLabel} ago`\n });\n }\n }\n\n const checkpointInfo = loadCheckpointTimestamp(vault.getPath());\n const activeUse =\n (latestDocAge !== null && latestDocAge <= ACTIVE_USE_DAYS) ||\n (lastHandoffAge !== null && lastHandoffAge <= ACTIVE_USE_DAYS);\n\n if (checkpointInfo.error) {\n checks.push({\n label: 'checkpoint freshness',\n status: 'warn',\n detail: checkpointInfo.error\n });\n warnings++;\n } else if (!checkpointInfo.timestamp) {\n const status = activeUse ? 'warn' : 'ok';\n if (status === 'warn') warnings++;\n checks.push({\n label: 'checkpoint freshness',\n status,\n detail: activeUse ? 'No checkpoint found' : 'No checkpoint found (vault appears inactive)',\n hint: activeUse ? 'Run `clawvault checkpoint` during heavy work.' : undefined\n });\n } else {\n const checkpointDate = new Date(checkpointInfo.timestamp);\n const checkpointAge = daysSince(checkpointDate);\n const ageLabel = describeAge(checkpointDate);\n if (activeUse && checkpointAge > 1) {\n checks.push({\n label: 'checkpoint freshness',\n status: 'warn',\n detail: `Last checkpoint ${ageLabel} ago`,\n hint: 'Checkpoint at least once per active day.'\n });\n warnings++;\n } else {\n checks.push({\n label: 'checkpoint freshness',\n status: 'ok',\n detail: `Last checkpoint ${ageLabel} ago`\n });\n }\n }\n\n const linkScan = scanVaultLinks(vault.getPath());\n if (linkScan.orphans.length > 20) {\n checks.push({\n label: 'orphan links',\n status: 'warn',\n detail: `${linkScan.orphans.length} orphan link(s)`,\n hint: 'Run `clawvault link --orphans` to review.'\n });\n warnings++;\n } else {\n checks.push({\n label: 'orphan links',\n status: 'ok',\n detail: `${linkScan.orphans.length} orphan link(s)`\n });\n }\n\n if (inbox.length > 5) {\n checks.push({\n label: 'inbox backlog',\n status: 'warn',\n detail: `${inbox.length} inbox item(s) pending`,\n hint: 'Process inbox items to keep memory tidy.'\n });\n warnings++;\n } else {\n checks.push({\n label: 'inbox backlog',\n status: 'ok',\n detail: `${inbox.length} inbox item(s) pending`\n });\n }\n\n if (stats.documents < 5) {\n checks.push({\n label: 'vault activity',\n status: 'warn',\n detail: `${stats.documents} total documents`,\n hint: 'Start capturing decisions, lessons, and projects.'\n });\n warnings++;\n }\n\n return { vaultPath: vault.getPath(), checks, warnings, errors };\n}\n",375 "inputSchema": {},376 "outputSchema": null,377 "icons": null,378 "annotations": null,379 "meta": null,380 "execution": null381 },382 {383 "name": "recover.test.ts",384 "title": null,385 "description": "Script: recover.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { checkDirtyDeathMock, clearDirtyFlagMock } = vi.hoisted(() => ({\n checkDirtyDeathMock: vi.fn(),\n clearDirtyFlagMock: vi.fn()\n}));\n\nvi.mock('./checkpoint.js', () => ({\n checkDirtyDeath: checkDirtyDeathMock,\n clearDirtyFlag: clearDirtyFlagMock\n}));\n\nimport { formatRecoveryInfo, recover } from './recover.js';\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-recover-'));\n}\n\nafterEach(() => {\n vi.clearAllMocks();\n});\n\ndescribe('recover', () => {\n it('returns clean startup info when no death is detected', async () => {\n checkDirtyDeathMock.mockResolvedValue({\n died: false,\n checkpoint: null,\n deathTime: null\n });\n\n const info = await recover('/tmp/vault');\n expect(info.died).toBe(false);\n expect(info.recoveryMessage).toBe('No context death detected. Clean startup.');\n expect(clearDirtyFlagMock).not.toHaveBeenCalled();\n });\n\n it('returns the latest handoff and clears the flag when requested', async () => {\n checkDirtyDeathMock.mockResolvedValue({\n died: true,\n deathTime: '2024-01-01T00:00:00Z',\n checkpoint: {\n timestamp: '2024-01-01T00:00:00Z',\n workingOn: 'feature',\n focus: 'tests',\n blocked: null\n }\n });\n\n const vaultPath = makeTempVaultDir();\n try {\n const handoffsDir = path.join(vaultPath, 'handoffs');\n fs.mkdirSync(handoffsDir, { recursive: true });\n fs.writeFileSync(path.join(handoffsDir, 'handoff-2024-01-01.md'), 'old handoff');\n fs.writeFileSync(path.join(handoffsDir, 'handoff-2024-01-02.md'), 'latest handoff');\n\n const info = await recover(vaultPath, { clearFlag: true });\n expect(info.died).toBe(true);\n expect(info.handoffPath).toBe(path.join(handoffsDir, 'handoff-2024-01-02.md'));\n expect(info.handoffContent).toBe('latest handoff');\n expect(info.recoveryMessage).toContain('CONTEXT DEATH DETECTED');\n expect(clearDirtyFlagMock).toHaveBeenCalledWith(vaultPath);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n});\n\ndescribe('formatRecoveryInfo', () => {\n it('includes verbose checkpoint and handoff content when requested', () => {\n const info = {\n died: true,\n deathTime: '2024-01-01T00:00:00Z',\n checkpoint: {\n timestamp: '2024-01-01T00:00:00Z',\n workingOn: 'feature',\n focus: 'tests',\n blocked: null,\n sessionKey: 'key',\n model: 'model',\n tokenEstimate: 100\n },\n handoffPath: '/tmp/vault/handoffs/handoff-2024-01-01.md',\n handoffContent: 'handoff text',\n recoveryMessage: 'message'\n };\n\n const output = formatRecoveryInfo(info, { verbose: true });\n expect(output).toContain('Checkpoint JSON:');\n expect(output).toContain('\"sessionKey\": \"key\"');\n expect(output).toContain('Handoff content:');\n expect(output).toContain('handoff text');\n });\n});\n",386 "inputSchema": {},387 "outputSchema": null,388 "icons": null,389 "annotations": null,390 "meta": null,391 "execution": null392 },393 {394 "name": "link.test.ts",395 "title": null,396 "description": "Script: link.test.ts. Code:\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { linkCommand } from './link.js';\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-link-'));\n}\n\nfunction writeFile(root: string, relative: string, content: string): void {\n const filePath = path.join(root, relative);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, content);\n}\n\ndescribe('link command', () => {\n let vaultPath = '';\n let originalEnv: string | undefined;\n\n beforeEach(() => {\n vaultPath = makeTempVaultDir();\n originalEnv = process.env.CLAWVAULT_PATH;\n process.env.CLAWVAULT_PATH = vaultPath;\n });\n\n afterEach(() => {\n if (originalEnv === undefined) {\n delete process.env.CLAWVAULT_PATH;\n } else {\n process.env.CLAWVAULT_PATH = originalEnv;\n }\n fs.rmSync(vaultPath, { recursive: true, force: true });\n vi.restoreAllMocks();\n });\n\n it('rebuilds backlinks and shows backlinks for a target', async () => {\n writeFile(vaultPath, 'people/alice.md', '# Alice');\n writeFile(vaultPath, 'notes/a.md', 'Met with [[people/alice]].');\n writeFile(vaultPath, 'notes/b.md', 'Followed up with [[people/alice]].');\n\n const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});\n\n await linkCommand(undefined, { rebuild: true });\n\n const backlinksPath = path.join(vaultPath, '.clawvault', 'backlinks.json');\n expect(fs.existsSync(backlinksPath)).toBe(true);\n\n logSpy.mockClear();\n await linkCommand(undefined, { backlinks: 'people/alice' });\n\n const output = logSpy.mock.calls.map(call => call.join(' ')).join('\\n');\n expect(output).toContain('Backlinks \u2192 people/alice');\n expect(output).toContain('notes/a');\n expect(output).toContain('notes/b');\n });\n\n it('lists orphan links', async () => {\n writeFile(vaultPath, 'notes/a.md', 'Reference to [[missing]].');\n\n const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});\n await linkCommand(undefined, { orphans: true });\n\n const output = logSpy.mock.calls.map(call => call.join(' ')).join('\\n');\n expect(output).toContain('orphan link(s) found');\n expect(output).toContain('[[missing]]');\n });\n});\n",397 "inputSchema": {},398 "outputSchema": null,399 "icons": null,400 "annotations": null,401 "meta": null,402 "execution": null403 },404 {405 "name": "status.ts",406 "title": null,407 "description": "Script: status.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { execFileSync } from 'child_process';\nimport { ClawVault } from '../lib/vault.js';\nimport { hasQmd, QmdUnavailableError } from '../lib/search.js';\nimport { formatAge } from '../lib/time.js';\nimport { scanVaultLinks } from '../lib/backlinks.js';\nimport type { CheckpointData } from './checkpoint.js';\n\nexport interface VaultStatus {\n vaultName: string;\n vaultPath: string;\n health: 'ok' | 'warning';\n issues: string[];\n checkpoint: {\n exists: boolean;\n timestamp?: string;\n age?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n };\n qmd: {\n collection: string;\n root: string;\n indexStatus: 'present' | 'missing' | 'root-mismatch';\n error?: string;\n };\n git?: {\n repoRoot: string;\n clean: boolean;\n dirtyCount: number;\n };\n links: {\n total: number;\n orphans: number;\n };\n documents: number;\n categories: Record<string, number>;\n}\n\nconst CLAWVAULT_DIR = '.clawvault';\nconst CHECKPOINT_FILE = 'last-checkpoint.json';\nconst DIRTY_DEATH_FLAG = 'dirty-death.flag';\n\nfunction findGitRoot(startPath: string): string | null {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, '.git'))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nfunction getGitStatus(repoRoot: string): { clean: boolean; dirtyCount: number } {\n const output = execFileSync('git', ['-C', repoRoot, 'status', '--porcelain'], {\n encoding: 'utf-8'\n });\n const lines = output.split('\\n').filter(Boolean);\n return { clean: lines.length === 0, dirtyCount: lines.length };\n}\n\n/**\n * Parse qmd collection list text output\n * Format:\n * Collections (N):\n *\n * name (qmd://name/)\n * Pattern: **\\/*.md\n * Files: 155\n * Updated: 1m ago\n */\nfunction parseQmdCollectionsText(raw: string): string[] {\n const names: string[] = [];\n // Match lines like \"memory (qmd://memory/)\"\n const regex = /^(\\S+)\\s+\\(qmd:\\/\\/\\1\\/\\)/gm;\n let match;\n while ((match = regex.exec(raw)) !== null) {\n names.push(match[1]);\n }\n return names;\n}\n\nfunction getQmdIndexStatus(collection: string, root: string): 'present' | 'missing' | 'root-mismatch' {\n // qmd collection list doesn't support --json, parse text output instead\n const output = execFileSync('qmd', ['collection', 'list'], { encoding: 'utf-8' });\n const names = parseQmdCollectionsText(output);\n \n if (names.includes(collection)) {\n return 'present';\n }\n\n return 'missing';\n}\n\nfunction loadCheckpoint(vaultPath: string): { data: CheckpointData | null; error?: string } {\n const checkpointPath = path.join(vaultPath, CLAWVAULT_DIR, CHECKPOINT_FILE);\n if (!fs.existsSync(checkpointPath)) {\n return { data: null };\n }\n try {\n const data = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8')) as CheckpointData;\n return { data };\n } catch (err: any) {\n return { data: null, error: err?.message || 'Failed to parse checkpoint' };\n }\n}\n\nexport async function getStatus(vaultPath: string): Promise<VaultStatus> {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n const stats = await vault.stats();\n const linkScan = scanVaultLinks(vault.getPath());\n\n const issues: string[] = [];\n const checkpointInfo = loadCheckpoint(vault.getPath());\n const checkpoint = checkpointInfo.data;\n\n if (checkpointInfo.error) {\n issues.push(`Checkpoint parse error: ${checkpointInfo.error}`);\n }\n\n const checkpointStatus: VaultStatus['checkpoint'] = {\n exists: Boolean(checkpoint),\n timestamp: checkpoint?.timestamp,\n age: checkpoint?.timestamp\n ? formatAge(Date.now() - new Date(checkpoint.timestamp).getTime())\n : undefined,\n sessionKey: checkpoint?.sessionKey,\n model: checkpoint?.model,\n tokenEstimate: checkpoint?.tokenEstimate\n };\n\n if (!checkpointStatus.exists) {\n issues.push('No checkpoint found');\n }\n\n const dirtyFlagPath = path.join(vault.getPath(), CLAWVAULT_DIR, DIRTY_DEATH_FLAG);\n if (fs.existsSync(dirtyFlagPath)) {\n issues.push('Dirty death flag is set');\n }\n\n const qmdCollection = vault.getQmdCollection();\n const qmdRoot = vault.getQmdRoot();\n let qmdIndexStatus: VaultStatus['qmd']['indexStatus'] = 'missing';\n let qmdError: string | undefined;\n try {\n qmdIndexStatus = getQmdIndexStatus(qmdCollection, qmdRoot);\n if (qmdIndexStatus !== 'present') {\n issues.push(`qmd collection ${qmdIndexStatus.replace('-', ' ')}`);\n }\n } catch (err: any) {\n qmdError = err?.message || 'Failed to check qmd index';\n issues.push(`qmd status error: ${qmdError}`);\n }\n\n let gitStatus: VaultStatus['git'] | undefined;\n const gitRoot = findGitRoot(vault.getPath());\n if (gitRoot) {\n try {\n const gitInfo = getGitStatus(gitRoot);\n gitStatus = { repoRoot: gitRoot, ...gitInfo };\n if (!gitInfo.clean) {\n issues.push(`Uncommitted changes: ${gitInfo.dirtyCount}`);\n }\n } catch (err: any) {\n issues.push(`Git status error: ${err?.message || 'unknown error'}`);\n }\n }\n\n return {\n vaultName: vault.getName(),\n vaultPath: vault.getPath(),\n health: issues.length === 0 ? 'ok' : 'warning',\n issues,\n checkpoint: checkpointStatus,\n qmd: {\n collection: qmdCollection,\n root: qmdRoot,\n indexStatus: qmdIndexStatus,\n error: qmdError\n },\n git: gitStatus,\n links: {\n total: linkScan.linkCount,\n orphans: linkScan.orphans.length\n },\n documents: stats.documents,\n categories: stats.categories\n };\n}\n\nexport function formatStatus(status: VaultStatus): string {\n let output = 'ClawVault Status\\n';\n output += '-'.repeat(40) + '\\n';\n output += `Vault: ${status.vaultName}\\n`;\n output += `Path: ${status.vaultPath}\\n`;\n output += `Health: ${status.health}\\n`;\n if (status.issues.length > 0) {\n output += `Issues: ${status.issues.join('; ')}\\n`;\n } else {\n output += 'Issues: none\\n';\n }\n\n output += '\\nCheckpoint:\\n';\n if (!status.checkpoint.exists) {\n output += ' - none\\n';\n } else {\n output += ` - Timestamp: ${status.checkpoint.timestamp}\\n`;\n if (status.checkpoint.age) {\n output += ` - Age: ${status.checkpoint.age}\\n`;\n }\n if (status.checkpoint.sessionKey) {\n output += ` - Session key: ${status.checkpoint.sessionKey}\\n`;\n }\n if (status.checkpoint.model) {\n output += ` - Model: ${status.checkpoint.model}\\n`;\n }\n if (status.checkpoint.tokenEstimate !== undefined) {\n output += ` - Token estimate: ${status.checkpoint.tokenEstimate}\\n`;\n }\n }\n\n output += '\\nqmd:\\n';\n output += ` - Collection: ${status.qmd.collection}\\n`;\n output += ` - Root: ${status.qmd.root}\\n`;\n output += ` - Index: ${status.qmd.indexStatus}\\n`;\n if (status.qmd.error) {\n output += ` - Error: ${status.qmd.error}\\n`;\n }\n\n if (status.git) {\n output += '\\nGit:\\n';\n output += ` - Repo: ${status.git.repoRoot}\\n`;\n output += ` - Status: ${status.git.clean ? 'clean' : 'dirty'} (${status.git.dirtyCount} change(s))\\n`;\n }\n\n output += '\\nLinks:\\n';\n output += ` - Total: ${status.links.total}\\n`;\n if (status.links.orphans > 0) {\n output += ` - Orphans: ${status.links.orphans}\\n`;\n }\n\n output += '\\nDocuments:\\n';\n output += ` - Total: ${status.documents}\\n`;\n output += ' - By category:\\n';\n for (const [category, count] of Object.entries(status.categories)) {\n output += ` * ${category}: ${count}\\n`;\n }\n\n output += '-'.repeat(40) + '\\n';\n return output;\n}\n\nexport async function statusCommand(\n vaultPath: string,\n options: { json?: boolean } = {}\n): Promise<void> {\n const status = await getStatus(vaultPath);\n if (options.json) {\n console.log(JSON.stringify(status, null, 2));\n return;\n }\n console.log(formatStatus(status));\n}\n",408 "inputSchema": {},409 "outputSchema": null,410 "icons": null,411 "annotations": null,412 "meta": null,413 "execution": null414 },415 {416 "name": "recover.ts",417 "title": null,418 "description": "Script: recover.ts. Code:\n/**\n * Recovery command - detect dirty death and provide recovery info\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { checkDirtyDeath, clearDirtyFlag, CheckpointData } from './checkpoint.js';\nimport { formatAge } from '../lib/time.js';\n\nexport interface RecoveryInfo {\n died: boolean;\n deathTime: string | null;\n checkpoint: CheckpointData | null;\n handoffPath: string | null;\n handoffContent: string | null;\n recoveryMessage: string;\n}\n\nexport async function recover(\n vaultPath: string,\n options: { clearFlag?: boolean; verbose?: boolean } = {}\n): Promise<RecoveryInfo> {\n const { clearFlag = false } = options;\n const { died, checkpoint, deathTime } = await checkDirtyDeath(vaultPath);\n \n if (!died) {\n return {\n died: false,\n deathTime: null,\n checkpoint: null,\n handoffPath: null,\n handoffContent: null,\n recoveryMessage: 'No context death detected. Clean startup.'\n };\n }\n \n // Find most recent handoff\n const handoffsDir = path.join(vaultPath, 'handoffs');\n let handoffPath: string | null = null;\n let handoffContent: string | null = null;\n \n if (fs.existsSync(handoffsDir)) {\n const files = fs.readdirSync(handoffsDir)\n .filter(f => f.startsWith('handoff-') && f.endsWith('.md'))\n .sort()\n .reverse();\n \n if (files.length > 0) {\n handoffPath = path.join(handoffsDir, files[0]);\n handoffContent = fs.readFileSync(handoffPath, 'utf-8');\n }\n }\n \n // Build recovery message\n let message = '\u26a0\ufe0f **CONTEXT DEATH DETECTED**\\n\\n';\n message += `Your previous session died at ${deathTime}.\\n\\n`;\n \n if (checkpoint) {\n message += '**Last known state:**\\n';\n if (checkpoint.workingOn) {\n message += `- Working on: ${checkpoint.workingOn}\\n`;\n }\n if (checkpoint.focus) {\n message += `- Focus: ${checkpoint.focus}\\n`;\n }\n if (checkpoint.blocked) {\n message += `- Blocked: ${checkpoint.blocked}\\n`;\n }\n message += '\\n';\n }\n \n if (handoffPath) {\n message += `**Last handoff:** ${path.basename(handoffPath)}\\n`;\n message += 'Review and resume from where you left off.\\n';\n } else {\n message += '**No handoff found.** You may have lost context.\\n';\n }\n \n // Clear the flag if requested\n if (clearFlag) {\n await clearDirtyFlag(vaultPath);\n }\n \n return {\n died: true,\n deathTime,\n checkpoint,\n handoffPath,\n handoffContent,\n recoveryMessage: message\n };\n}\n\n/**\n * Format recovery info for CLI output\n */\nexport function formatRecoveryInfo(info: RecoveryInfo, options: { verbose?: boolean } = {}): string {\n const { verbose = false } = options;\n if (!info.died) {\n return '\u2713 Clean startup - no context death detected.';\n }\n \n let output = '\\n\u26a0\ufe0f CONTEXT DEATH DETECTED\\n';\n output += '\u2550'.repeat(40) + '\\n\\n';\n output += `Death time: ${info.deathTime}\\n`;\n if (info.checkpoint?.timestamp) {\n const age = formatAge(Date.now() - new Date(info.checkpoint.timestamp).getTime());\n output += `Checkpoint: ${info.checkpoint.timestamp} (${age} ago)\\n`;\n }\n output += '\\n';\n \n if (info.checkpoint) {\n output += 'Last checkpoint:\\n';\n if (info.checkpoint.workingOn) {\n output += ` \u2022 Working on: ${info.checkpoint.workingOn}\\n`;\n }\n if (info.checkpoint.focus) {\n output += ` \u2022 Focus: ${info.checkpoint.focus}\\n`;\n }\n if (info.checkpoint.blocked) {\n output += ` \u2022 Blocked: ${info.checkpoint.blocked}\\n`;\n }\n if (info.checkpoint.sessionKey || info.checkpoint.model || info.checkpoint.tokenEstimate !== undefined) {\n output += ' \u2022 Session:\\n';\n if (info.checkpoint.sessionKey) {\n output += ` - Key: ${info.checkpoint.sessionKey}\\n`;\n }\n if (info.checkpoint.model) {\n output += ` - Model: ${info.checkpoint.model}\\n`;\n }\n if (info.checkpoint.tokenEstimate !== undefined) {\n output += ` - Token estimate: ${info.checkpoint.tokenEstimate}\\n`;\n }\n }\n output += '\\n';\n } else {\n output += 'No checkpoint data found.\\n\\n';\n }\n \n if (info.handoffPath) {\n output += `Last handoff: ${path.basename(info.handoffPath)}\\n`;\n } else {\n output += 'No handoff found - context may be lost.\\n';\n }\n \n if (verbose) {\n if (info.checkpoint) {\n output += '\\nCheckpoint JSON:\\n';\n output += JSON.stringify(info.checkpoint, null, 2) + '\\n';\n }\n if (info.handoffContent) {\n output += '\\nHandoff content:\\n';\n output += info.handoffContent.trim() + '\\n';\n }\n }\n\n output += '\\n' + '\u2550'.repeat(40) + '\\n';\n output += 'Run `clawvault recap` to see full context.\\n';\n \n return output;\n}\n",419 "inputSchema": {},420 "outputSchema": null,421 "icons": null,422 "annotations": null,423 "meta": null,424 "execution": null425 },426 {427 "name": "setup.test.ts",428 "title": null,429 "description": "Script: setup.test.ts. Code:\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { hasQmdMock } = vi.hoisted(() => ({\n hasQmdMock: vi.fn()\n}));\n\nvi.mock('../lib/search.js', async () => {\n const actual = await vi.importActual<typeof import('../lib/search.js')>('../lib/search.js');\n return {\n ...actual,\n hasQmd: hasQmdMock\n };\n});\n\nimport { setupCommand } from './setup.js';\n\ndescribe('setup command', () => {\n let baseDir: string;\n let vaultPath: string;\n\n beforeEach(() => {\n baseDir = fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-setup-'));\n vaultPath = path.join(baseDir, 'vault');\n process.env.CLAWVAULT_PATH = vaultPath;\n });\n\n afterEach(() => {\n delete process.env.CLAWVAULT_PATH;\n fs.rmSync(baseDir, { recursive: true, force: true });\n vi.clearAllMocks();\n });\n\n it('creates a vault at CLAWVAULT_PATH when set', async () => {\n hasQmdMock.mockReturnValue(false);\n // Ensure the path doesn't exist before setup\n expect(fs.existsSync(vaultPath)).toBe(false);\n await setupCommand();\n // CLAWVAULT_PATH should be used even if OpenClaw default exists\n expect(fs.existsSync(vaultPath)).toBe(true);\n expect(fs.existsSync(path.join(vaultPath, '.clawvault.json'))).toBe(true);\n expect(fs.existsSync(path.join(vaultPath, 'inbox'))).toBe(true);\n });\n});\n",430 "inputSchema": {},431 "outputSchema": null,432 "icons": null,433 "annotations": null,434 "meta": null,435 "execution": null436 },437 {438 "name": "repair-session.test.ts",439 "title": null,440 "description": "Script: repair-session.test.ts. Code:\n/**\n * Tests for session repair functionality\n */\n\nimport { describe, it, expect, beforeEach, afterEach } from 'vitest';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n parseTranscript,\n extractToolUses,\n findCorruptedEntries,\n computeParentRelinks,\n analyzeSession,\n repairSession,\n type TranscriptEntry\n} from '../lib/session-repair.js';\n\n// Test fixtures\nconst CLEAN_SESSION = [\n { type: 'session', version: 3, id: 'test-session-clean', timestamp: '2026-01-01T00:00:00.000Z' },\n { type: 'message', id: 'msg-1', parentId: null, timestamp: '2026-01-01T00:00:01.000Z', message: { role: 'user', content: [{ type: 'text', text: 'Hello' }] } },\n { type: 'message', id: 'msg-2', parentId: 'msg-1', timestamp: '2026-01-01T00:00:02.000Z', message: { role: 'assistant', content: [{ type: 'text', text: 'Hi there!' }, { type: 'toolCall', id: 'toolu_123', name: 'exec', arguments: { command: 'ls' } }], stopReason: 'toolUse' } },\n { type: 'message', id: 'msg-3', parentId: 'msg-2', timestamp: '2026-01-01T00:00:03.000Z', message: { role: 'toolResult', toolCallId: 'toolu_123', content: [{ type: 'text', text: 'file1.txt\\nfile2.txt' }] } },\n { type: 'message', id: 'msg-4', parentId: 'msg-3', timestamp: '2026-01-01T00:00:04.000Z', message: { role: 'assistant', content: [{ type: 'text', text: 'Found 2 files.' }], stopReason: 'stop' } }\n];\n\nconst CORRUPTED_SESSION = [\n { type: 'session', version: 3, id: 'test-session-corrupted', timestamp: '2026-01-01T00:00:00.000Z' },\n { type: 'message', id: 'msg-1', parentId: null, timestamp: '2026-01-01T00:00:01.000Z', message: { role: 'user', content: [{ type: 'text', text: 'Hello' }] } },\n // Aborted tool call with partialJson\n { type: 'message', id: 'msg-2', parentId: 'msg-1', timestamp: '2026-01-01T00:00:02.000Z', message: { role: 'assistant', content: [{ type: 'toolCall', id: 'toolu_aborted', name: 'exec', arguments: { command: 'long' }, partialJson: '{\"command\": \"long' }], stopReason: 'aborted' } },\n // Orphaned tool result referencing aborted call\n { type: 'message', id: 'msg-3', parentId: 'msg-2', timestamp: '2026-01-01T00:00:03.000Z', message: { role: 'toolResult', toolCallId: 'toolu_aborted', content: [{ type: 'text', text: 'synthetic error' }], isError: true } },\n // Next valid message that needs relinking\n { type: 'message', id: 'msg-4', parentId: 'msg-3', timestamp: '2026-01-01T00:00:04.000Z', message: { role: 'user', content: [{ type: 'text', text: 'What happened?' }] } }\n];\n\nconst ORPHAN_ONLY_SESSION = [\n { type: 'session', version: 3, id: 'test-session-orphan', timestamp: '2026-01-01T00:00:00.000Z' },\n { type: 'message', id: 'msg-1', parentId: null, timestamp: '2026-01-01T00:00:01.000Z', message: { role: 'user', content: [{ type: 'text', text: 'Hello' }] } },\n // Orphaned tool result with no matching tool call at all\n { type: 'message', id: 'msg-2', parentId: 'msg-1', timestamp: '2026-01-01T00:00:02.000Z', message: { role: 'toolResult', toolCallId: 'toolu_nonexistent', content: [{ type: 'text', text: 'phantom result' }] } },\n { type: 'message', id: 'msg-3', parentId: 'msg-2', timestamp: '2026-01-01T00:00:03.000Z', message: { role: 'assistant', content: [{ type: 'text', text: 'Continuing...' }] } }\n];\n\nfunction createTempSession(entries: unknown[]): string {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-test-'));\n const filePath = path.join(tmpDir, 'test-session.jsonl');\n const content = entries.map(e => JSON.stringify(e)).join('\\n') + '\\n';\n fs.writeFileSync(filePath, content);\n return filePath;\n}\n\nfunction cleanupTempSession(filePath: string): void {\n const dir = path.dirname(filePath);\n fs.rmSync(dir, { recursive: true, force: true });\n}\n\ndescribe('parseTranscript', () => {\n it('parses valid JSONL file', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const entries = parseTranscript(filePath);\n expect(entries).toHaveLength(5);\n expect(entries[0].entry.type).toBe('session');\n expect(entries[1].entry.id).toBe('msg-1');\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('extractToolUses', () => {\n it('extracts tool_use IDs from assistant messages', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n \n expect(toolUses.size).toBe(1);\n expect(toolUses.has('toolu_123')).toBe(true);\n \n const info = toolUses.get('toolu_123')!;\n expect(info.name).toBe('exec');\n expect(info.isAborted).toBe(false);\n expect(info.isPartial).toBe(false);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('marks aborted tool calls correctly', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n \n expect(toolUses.size).toBe(1);\n expect(toolUses.has('toolu_aborted')).toBe(true);\n \n const info = toolUses.get('toolu_aborted')!;\n expect(info.isAborted).toBe(true);\n expect(info.isPartial).toBe(true);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('findCorruptedEntries', () => {\n it('finds no corruption in clean session', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n \n expect(corrupted).toHaveLength(0);\n expect(entriesToRemove.size).toBe(0);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('finds aborted tool_use and orphaned tool_result', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n \n expect(corrupted).toHaveLength(2);\n expect(corrupted[0].type).toBe('aborted_tool_use');\n expect(corrupted[1].type).toBe('orphaned_tool_result');\n expect(entriesToRemove.size).toBe(2);\n expect(entriesToRemove.has('msg-2')).toBe(true);\n expect(entriesToRemove.has('msg-3')).toBe(true);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('finds orphaned tool_result without any matching tool_use', () => {\n const filePath = createTempSession(ORPHAN_ONLY_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n \n expect(corrupted).toHaveLength(1);\n expect(corrupted[0].type).toBe('orphaned_tool_result');\n expect(corrupted[0].toolUseId).toBe('toolu_nonexistent');\n expect(entriesToRemove.size).toBe(1);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('computeParentRelinks', () => {\n it('computes correct parent relinks', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n const { entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const relinks = computeParentRelinks(entries, entriesToRemove);\n \n // msg-4 should be relinked from msg-3 to msg-1\n expect(relinks).toHaveLength(1);\n expect(relinks[0].entryId).toBe('msg-4');\n expect(relinks[0].oldParentId).toBe('msg-3');\n expect(relinks[0].newParentId).toBe('msg-1');\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('analyzeSession', () => {\n it('returns clean result for clean session', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const result = analyzeSession(filePath);\n \n expect(result.sessionId).toBe('test-session-clean');\n expect(result.corruptedEntries).toHaveLength(0);\n expect(result.parentRelinks).toHaveLength(0);\n expect(result.removedCount).toBe(0);\n expect(result.repaired).toBe(false);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('detects corruption in corrupted session', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const result = analyzeSession(filePath);\n \n expect(result.sessionId).toBe('test-session-corrupted');\n expect(result.corruptedEntries).toHaveLength(2);\n expect(result.parentRelinks).toHaveLength(1);\n expect(result.removedCount).toBe(2);\n expect(result.repaired).toBe(false);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('repairSession', () => {\n it('does not modify clean session', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const result = repairSession(filePath, { backup: false });\n \n expect(result.repaired).toBe(false);\n expect(result.removedCount).toBe(0);\n \n // Verify file unchanged\n const entries = parseTranscript(filePath);\n expect(entries).toHaveLength(5);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('repairs corrupted session', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const result = repairSession(filePath, { backup: false });\n \n expect(result.repaired).toBe(true);\n expect(result.removedCount).toBe(2);\n expect(result.relinkedCount).toBe(1);\n \n // Verify file was repaired\n const entries = parseTranscript(filePath);\n expect(entries).toHaveLength(3); // session + msg-1 + msg-4\n \n // Check msg-4 was relinked to msg-1\n const msg4 = entries.find(e => e.entry.id === 'msg-4');\n expect(msg4?.entry.parentId).toBe('msg-1');\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('creates backup when requested', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const result = repairSession(filePath, { backup: true });\n \n expect(result.backupPath).toBeDefined();\n expect(fs.existsSync(result.backupPath!)).toBe(true);\n \n // Backup should contain original content\n const backupEntries = parseTranscript(result.backupPath!);\n expect(backupEntries).toHaveLength(5);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('dry-run mode does not modify file', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n const originalContent = fs.readFileSync(filePath, 'utf-8');\n \n try {\n const result = repairSession(filePath, { backup: false, dryRun: true });\n \n expect(result.repaired).toBe(false);\n expect(result.corruptedEntries).toHaveLength(2);\n \n // File should be unchanged\n const currentContent = fs.readFileSync(filePath, 'utf-8');\n expect(currentContent).toBe(originalContent);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n",441 "inputSchema": {},442 "outputSchema": null,443 "icons": null,444 "annotations": null,445 "meta": null,446 "execution": null447 },448 {449 "name": "status.test.ts",450 "title": null,451 "description": "Script: status.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { execFileSyncMock, hasQmdMock } = vi.hoisted(() => ({\n execFileSyncMock: vi.fn(),\n hasQmdMock: vi.fn()\n}));\n\nlet mockStats = { documents: 0, categories: {} as Record<string, number> };\nlet mockCollection = 'vault';\nlet mockRoot = '';\n\nvi.mock('child_process', () => ({\n execFileSync: execFileSyncMock\n}));\n\nvi.mock('../lib/search.js', async () => {\n const actual = await vi.importActual<typeof import('../lib/search.js')>('../lib/search.js');\n return {\n ...actual,\n hasQmd: hasQmdMock\n };\n});\n\nvi.mock('../lib/vault.js', () => ({\n ClawVault: class {\n private vaultPath: string;\n\n constructor(vaultPath: string) {\n this.vaultPath = vaultPath;\n }\n\n async load(): Promise<void> {\n return;\n }\n\n async stats(): Promise<{ documents: number; categories: Record<string, number> }> {\n return mockStats;\n }\n\n getPath(): string {\n return this.vaultPath;\n }\n\n getName(): string {\n return mockCollection;\n }\n\n getQmdCollection(): string {\n return mockCollection;\n }\n\n getQmdRoot(): string {\n return mockRoot || this.vaultPath;\n }\n }\n}));\n\nimport { getStatus, formatStatus } from './status.js';\nimport { QmdUnavailableError } from '../lib/search.js';\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-status-'));\n}\n\nafterEach(() => {\n vi.clearAllMocks();\n});\n\ndescribe('status command', () => {\n it('throws when qmd is unavailable', async () => {\n hasQmdMock.mockReturnValue(false);\n await expect(getStatus('/tmp/vault')).rejects.toBeInstanceOf(QmdUnavailableError);\n });\n\n it('reports issues when checkpoint is missing and git/qmd are dirty', async () => {\n hasQmdMock.mockReturnValue(true);\n execFileSyncMock.mockImplementation((command: string) => {\n if (command === 'qmd') {\n return JSON.stringify([{ name: 'other', root: '/somewhere' }]);\n }\n if (command === 'git') {\n return ' M file.md\\n?? new.md\\n';\n }\n return '';\n });\n\n const vaultPath = makeTempVaultDir();\n try {\n fs.mkdirSync(path.join(vaultPath, '.git'), { recursive: true });\n const clawvaultDir = path.join(vaultPath, '.clawvault');\n fs.mkdirSync(clawvaultDir, { recursive: true });\n fs.writeFileSync(path.join(clawvaultDir, 'dirty-death.flag'), '2024-01-01T00:00:00Z');\n\n mockStats = { documents: 2, categories: { inbox: 2 } };\n mockCollection = 'vault';\n mockRoot = vaultPath;\n\n const status = await getStatus(vaultPath);\n expect(status.health).toBe('warning');\n expect(status.issues).toEqual(\n expect.arrayContaining([\n 'No checkpoint found',\n 'Dirty death flag is set',\n 'qmd collection missing',\n 'Uncommitted changes: 2'\n ])\n );\n expect(status.git?.dirtyCount).toBe(2);\n expect(status.qmd.indexStatus).toBe('missing');\n expect(status.links.total).toBe(0);\n expect(status.links.orphans).toBe(0);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('returns ok status when everything is healthy', async () => {\n hasQmdMock.mockReturnValue(true);\n execFileSyncMock.mockImplementation((command: string) => {\n if (command === 'qmd') {\n return JSON.stringify([{ name: mockCollection, root: mockRoot }]);\n }\n if (command === 'git') {\n return '';\n }\n return '';\n });\n\n const vaultPath = makeTempVaultDir();\n try {\n fs.mkdirSync(path.join(vaultPath, '.git'), { recursive: true });\n const clawvaultDir = path.join(vaultPath, '.clawvault');\n fs.mkdirSync(clawvaultDir, { recursive: true });\n const timestamp = new Date(Date.now() - 60_000).toISOString();\n fs.writeFileSync(\n path.join(clawvaultDir, 'last-checkpoint.json'),\n JSON.stringify({ timestamp, workingOn: 'sync', focus: null, blocked: null }, null, 2)\n );\n\n mockStats = { documents: 1, categories: { inbox: 1 } };\n mockCollection = 'vault';\n mockRoot = vaultPath;\n\n const status = await getStatus(vaultPath);\n expect(status.health).toBe('ok');\n expect(status.issues).toHaveLength(0);\n expect(status.checkpoint.exists).toBe(true);\n expect(status.qmd.indexStatus).toBe('present');\n expect(status.links.total).toBe(0);\n expect(status.links.orphans).toBe(0);\n const formatted = formatStatus(status);\n expect(formatted).toContain('Issues: none');\n expect(formatted).toContain('Links:');\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n});\n",452 "inputSchema": {},453 "outputSchema": null,454 "icons": null,455 "annotations": null,456 "meta": null,457 "execution": null458 },459 {460 "name": "sleep.ts",461 "title": null,462 "description": "Script: sleep.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as readline from 'readline';\nimport { execFileSync } from 'child_process';\nimport { ClawVault } from '../lib/vault.js';\nimport { qmdUpdate } from '../lib/search.js';\nimport type { Document, HandoffDocument } from '../types.js';\nimport { clearDirtyFlag } from './checkpoint.js';\n\nexport type PromptFn = (question: string) => Promise<string>;\n\nexport interface SleepOptions {\n workingOn: string;\n next?: string;\n blocked?: string;\n decisions?: string;\n questions?: string;\n feeling?: string;\n sessionKey?: string;\n vaultPath: string;\n index?: boolean;\n git?: boolean;\n prompt?: PromptFn;\n cwd?: string;\n}\n\nexport interface GitCommitResult {\n repoRoot?: string;\n dirtyCount?: number;\n committed: boolean;\n message?: string;\n skippedReason?: string;\n}\n\nexport interface SleepResult {\n handoff: HandoffDocument;\n document: Document;\n git?: GitCommitResult;\n}\n\nfunction isInteractive(): boolean {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\n\nasync function defaultPrompt(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nfunction parseList(raw?: string): string[] {\n if (!raw) return [];\n return raw\n .split(',')\n .map(item => item.trim())\n .filter(Boolean);\n}\n\nfunction ensureNonEmpty(label: string, items: string[]): void {\n if (items.length === 0) {\n throw new Error(`${label} is required.`);\n }\n}\n\nasync function promptForList(\n label: string,\n prompt: PromptFn,\n interactive: boolean\n): Promise<string[]> {\n if (!interactive) return [];\n const answer = await prompt(`${label} (comma-separated, empty to skip): `);\n return parseList(answer);\n}\n\nfunction findGitRoot(startPath: string): string | null {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, '.git'))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nfunction getGitStatus(repoRoot: string): { clean: boolean; dirtyCount: number } {\n const output = execFileSync('git', ['-C', repoRoot, 'status', '--porcelain'], {\n encoding: 'utf-8'\n });\n const lines = output.split('\\n').filter(Boolean);\n return { clean: lines.length === 0, dirtyCount: lines.length };\n}\n\nfunction isAffirmative(input: string): boolean {\n const normalized = input.trim().toLowerCase();\n return normalized === 'y' || normalized === 'yes';\n}\n\nasync function maybeCommitDirtyRepo(options: {\n enabled: boolean;\n prompt: PromptFn;\n cwd: string;\n interactive: boolean;\n}): Promise<GitCommitResult | undefined> {\n if (!options.enabled) {\n return { committed: false, skippedReason: 'disabled' };\n }\n\n const repoRoot = findGitRoot(options.cwd);\n if (!repoRoot) {\n return { committed: false, skippedReason: 'no-repo' };\n }\n\n let status: { clean: boolean; dirtyCount: number };\n try {\n status = getGitStatus(repoRoot);\n } catch (err: any) {\n if (err?.code === 'ENOENT') {\n return { committed: false, skippedReason: 'git-missing' };\n }\n return { repoRoot, committed: false, skippedReason: 'status-error' };\n }\n\n if (status.clean) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: 'clean' };\n }\n\n if (!options.interactive) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: 'non-interactive' };\n }\n\n const confirm = await options.prompt(\n `Git repo dirty (${status.dirtyCount} change(s)). Commit before sleep? (y/N): `\n );\n if (!isAffirmative(confirm)) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: 'declined' };\n }\n\n const message = await options.prompt('Commit message: ');\n if (!message) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: 'no-message' };\n }\n\n try {\n execFileSync('git', ['-C', repoRoot, 'add', '-A'], { stdio: 'inherit' });\n execFileSync('git', ['-C', repoRoot, 'commit', '-m', message], { stdio: 'inherit' });\n } catch (err: any) {\n throw new Error(`Git commit failed: ${err?.message || 'unknown error'}`);\n }\n\n return {\n repoRoot,\n dirtyCount: status.dirtyCount,\n committed: true,\n message\n };\n}\n\nexport async function sleep(options: SleepOptions): Promise<SleepResult> {\n const prompt = options.prompt ?? defaultPrompt;\n const interactive = isInteractive();\n const workingOn = parseList(options.workingOn);\n ensureNonEmpty('Working-on summary', workingOn);\n\n const nextProvided = options.next !== undefined;\n const blockedProvided = options.blocked !== undefined;\n\n let nextSteps = parseList(options.next);\n let blocked = parseList(options.blocked);\n\n if (!nextProvided) {\n nextSteps = await promptForList('Next steps', prompt, interactive);\n }\n\n if (!blockedProvided) {\n blocked = await promptForList('Blocked items', prompt, interactive);\n }\n\n const decisions = parseList(options.decisions);\n const questions = parseList(options.questions);\n\n const vault = new ClawVault(path.resolve(options.vaultPath));\n await vault.load();\n\n const handoffInput = {\n workingOn,\n blocked,\n nextSteps,\n decisions: decisions.length > 0 ? decisions : undefined,\n openQuestions: questions.length > 0 ? questions : undefined,\n feeling: options.feeling,\n sessionKey: options.sessionKey\n };\n\n const document = await vault.createHandoff(handoffInput);\n const handoff: HandoffDocument = {\n ...handoffInput,\n created: document.modified.toISOString()\n };\n await clearDirtyFlag(vault.getPath());\n\n if (options.index) {\n qmdUpdate(vault.getQmdCollection());\n }\n\n const git = await maybeCommitDirtyRepo({\n enabled: options.git !== false,\n prompt,\n cwd: options.cwd ?? process.cwd(),\n interactive\n });\n\n return { handoff, document, git };\n}\n",463 "inputSchema": {},464 "outputSchema": null,465 "icons": null,466 "annotations": null,467 "meta": null,468 "execution": null469 },470 {471 "name": "link.ts",472 "title": null,473 "description": "Script: link.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { buildEntityIndex, type EntityIndex } from '../lib/entity-index.js';\nimport { autoLink, dryRunLink, findUnlinkedMentions } from '../lib/auto-linker.js';\nimport { readBacklinksIndex, rebuildBacklinksIndex, scanVaultLinks } from '../lib/backlinks.js';\nimport { getVaultPath } from '../lib/config.js';\n\ninterface LinkOptions {\n all?: boolean;\n dryRun?: boolean;\n backlinks?: string;\n orphans?: boolean;\n rebuild?: boolean;\n}\n\nexport async function linkCommand(file: string | undefined, options: LinkOptions): Promise<void> {\n const vaultPath = getVaultPath();\n const index = buildEntityIndex(vaultPath);\n const suggestionIndex = filterIndex(index, new Set(['people', 'projects', 'decisions']));\n const modeCount = [options.backlinks ? 1 : 0, options.orphans ? 1 : 0, options.rebuild ? 1 : 0]\n .reduce((sum, value) => sum + value, 0);\n\n if (modeCount > 1) {\n console.error('Error: Use only one of --backlinks, --orphans, or --rebuild');\n process.exit(1);\n }\n\n if (options.rebuild) {\n const result = rebuildBacklinksIndex(vaultPath, { entityIndex: index });\n const orphanSuffix = result.orphans.length > 0 ? `, ${result.orphans.length} orphan(s)` : '';\n console.log(`\u2713 Rebuilt backlinks (${result.backlinks.size} targets, ${result.linkCount} links${orphanSuffix})`);\n return;\n }\n\n if (options.backlinks) {\n if (file) {\n console.error('Error: Use --backlinks without a file argument');\n process.exit(1);\n }\n const target = resolveBacklinkTarget(options.backlinks, vaultPath, index);\n if (!target) {\n console.error('Error: Invalid target for --backlinks');\n process.exit(1);\n }\n const backlinks = readBacklinksIndex(vaultPath)\n ?? rebuildBacklinksIndex(vaultPath, { entityIndex: index }).backlinks;\n const sources = backlinks.get(target) || [];\n if (sources.length === 0) {\n console.log(`No backlinks found for ${target}`);\n return;\n }\n console.log(`Backlinks \u2192 ${target}`);\n for (const source of sources.sort()) {\n console.log(` - ${source}`);\n }\n return;\n }\n\n if (options.orphans) {\n if (file || options.all) {\n console.error('Error: --orphans does not accept a file or --all');\n process.exit(1);\n }\n const result = scanVaultLinks(vaultPath, { entityIndex: index });\n if (result.orphans.length === 0) {\n console.log('\u2713 No orphan links found');\n return;\n }\n const orphans = result.orphans\n .slice()\n .sort((a, b) => a.target.localeCompare(b.target) || a.source.localeCompare(b.source));\n console.log(`\u26a0 ${orphans.length} orphan link(s) found`);\n for (const orphan of orphans) {\n console.log(` - ${orphan.source} \u2192 [[${orphan.target}]]`);\n }\n return;\n }\n \n if (options.all) {\n await linkAllFiles(vaultPath, index, suggestionIndex, options.dryRun);\n return;\n }\n \n if (!file) {\n console.error('Error: Specify a file or use --all');\n process.exit(1);\n }\n \n const filePath = path.isAbsolute(file) ? file : path.join(process.cwd(), file);\n \n if (!fs.existsSync(filePath)) {\n console.error(`Error: File not found: ${filePath}`);\n process.exit(1);\n }\n \n await linkFile(filePath, index, suggestionIndex, options.dryRun);\n}\n\nfunction filterIndex(index: EntityIndex, categories: Set<string>): EntityIndex {\n const entries = new Map<string, string>();\n const byPath = new Map<string, { path: string; aliases: string[] }>();\n\n for (const [alias, targetPath] of index.entries) {\n const category = targetPath.split('/')[0];\n if (categories.has(category)) {\n entries.set(alias, targetPath);\n }\n }\n\n for (const [targetPath, entry] of index.byPath) {\n const category = targetPath.split('/')[0];\n if (categories.has(category)) {\n byPath.set(targetPath, entry);\n }\n }\n\n return { entries, byPath };\n}\n\nfunction resolveBacklinkTarget(input: string, vaultPath: string, index: EntityIndex): string | null {\n let target = input.trim();\n if (!target) return null;\n if (target.startsWith('[[') && target.endsWith(']]')) {\n target = target.slice(2, -2);\n }\n const pipeIndex = target.indexOf('|');\n if (pipeIndex !== -1) {\n target = target.slice(0, pipeIndex);\n }\n const hashIndex = target.indexOf('#');\n if (hashIndex !== -1) {\n target = target.slice(0, hashIndex);\n }\n target = target.trim();\n if (!target) return null;\n if (target.endsWith('.md')) {\n target = target.slice(0, -3);\n }\n if (target.startsWith('/')) {\n target = target.slice(1);\n }\n\n const candidate = path.isAbsolute(target) ? target : path.join(vaultPath, target);\n const withExtension = candidate.endsWith('.md') ? candidate : `${candidate}.md`;\n if (fs.existsSync(candidate) && candidate.endsWith('.md')) {\n return toVaultId(vaultPath, candidate);\n }\n if (fs.existsSync(withExtension)) {\n return toVaultId(vaultPath, withExtension);\n }\n\n const aliasKey = target.toLowerCase();\n if (index.entries.has(aliasKey)) {\n return index.entries.get(aliasKey)!;\n }\n\n return target.replace(/\\\\/g, '/');\n}\n\nfunction toVaultId(vaultPath: string, filePath: string): string {\n const relative = path.relative(vaultPath, filePath).replace(/\\.md$/, '');\n return relative.split(path.sep).join('/');\n}\n\nfunction logSuggestions(filePath: string, suggestions: Array<{ alias: string; path: string; line: number }>): void {\n if (suggestions.length === 0) return;\n console.log(`\\n\ud83d\udca1 Suggested links in ${path.basename(filePath)}`);\n for (const suggestion of suggestions) {\n console.log(` Line ${suggestion.line}: \"${suggestion.alias}\" \u2192 [[${suggestion.path}]]`);\n }\n}\n\nasync function linkFile(\n filePath: string,\n index: ReturnType<typeof buildEntityIndex>,\n suggestionIndex: EntityIndex,\n dryRun?: boolean\n): Promise<number> {\n const content = fs.readFileSync(filePath, 'utf-8');\n const linkedContent = autoLink(content, index);\n const suggestions = findUnlinkedMentions(linkedContent, suggestionIndex);\n\n if (dryRun) {\n const matches = dryRunLink(content, index);\n if (matches.length > 0) {\n console.log(`\\n\ud83d\udcc4 ${filePath}`);\n for (const m of matches) {\n console.log(` Line ${m.line}: \"${m.alias}\" \u2192 [[${m.path}]]`);\n }\n }\n logSuggestions(filePath, suggestions);\n return matches.length;\n }\n\n if (linkedContent !== content) {\n fs.writeFileSync(filePath, linkedContent);\n const matches = dryRunLink(content, index);\n console.log(`\u2713 Linked ${matches.length} entities in ${path.basename(filePath)}`);\n logSuggestions(filePath, suggestions);\n return matches.length;\n }\n\n logSuggestions(filePath, suggestions);\n return 0;\n}\n\nasync function linkAllFiles(\n vaultPath: string,\n index: ReturnType<typeof buildEntityIndex>,\n suggestionIndex: EntityIndex,\n dryRun?: boolean\n): Promise<void> {\n const files: string[] = [];\n \n function walk(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n // Skip hidden folders and archive\n if (!entry.name.startsWith('.') && entry.name !== 'archive' && entry.name !== 'templates') {\n walk(fullPath);\n }\n } else if (entry.name.endsWith('.md')) {\n files.push(fullPath);\n }\n }\n }\n \n walk(vaultPath);\n \n let totalLinks = 0;\n let filesModified = 0;\n \n for (const file of files) {\n const links = await linkFile(file, index, suggestionIndex, dryRun);\n if (links > 0) {\n totalLinks += links;\n filesModified++;\n }\n }\n \n console.log(`\\n${dryRun ? '(dry run) ' : ''}${totalLinks} links in ${filesModified} files`);\n}\n",474 "inputSchema": {},475 "outputSchema": null,476 "icons": null,477 "annotations": null,478 "meta": null,479 "execution": null480 },481 {482 "name": "checkpoint.test.ts",483 "title": null,484 "description": "Script: checkpoint.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { execFileSyncMock } = vi.hoisted(() => ({\n execFileSyncMock: vi.fn()\n}));\n\nvi.mock('child_process', () => ({\n execFileSync: execFileSyncMock\n}));\n\nconst envSnapshot = {\n OPENCLAW_SESSION_KEY: process.env.OPENCLAW_SESSION_KEY,\n OPENCLAW_MODEL: process.env.OPENCLAW_MODEL,\n OPENCLAW_TOKEN_ESTIMATE: process.env.OPENCLAW_TOKEN_ESTIMATE,\n OPENCLAW_CONTEXT_TOKENS: process.env.OPENCLAW_CONTEXT_TOKENS\n};\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-test-'));\n}\n\nasync function loadCheckpointModule() {\n vi.resetModules();\n return await import('./checkpoint.js');\n}\n\nafterEach(() => {\n vi.clearAllMocks();\n vi.useRealTimers();\n process.env.OPENCLAW_SESSION_KEY = envSnapshot.OPENCLAW_SESSION_KEY;\n process.env.OPENCLAW_MODEL = envSnapshot.OPENCLAW_MODEL;\n process.env.OPENCLAW_TOKEN_ESTIMATE = envSnapshot.OPENCLAW_TOKEN_ESTIMATE;\n process.env.OPENCLAW_CONTEXT_TOKENS = envSnapshot.OPENCLAW_CONTEXT_TOKENS;\n});\n\ndescribe('checkpoint debounce', () => {\n it('coalesces rapid checkpoint calls into a single disk write', async () => {\n vi.useFakeTimers();\n const { checkpoint } = await loadCheckpointModule();\n\n const vaultPath = makeTempVaultDir();\n try {\n const checkpointPath = path.join(vaultPath, '.clawvault', 'last-checkpoint.json');\n\n await checkpoint({ vaultPath, workingOn: 'a' });\n await vi.advanceTimersByTimeAsync(500);\n await checkpoint({ vaultPath, workingOn: 'b' });\n await vi.advanceTimersByTimeAsync(500);\n await checkpoint({ vaultPath, workingOn: 'c' });\n\n // Timer should have been reset by the last call.\n await vi.advanceTimersByTimeAsync(999);\n expect(fs.existsSync(checkpointPath)).toBe(false);\n\n await vi.advanceTimersByTimeAsync(1);\n expect(fs.existsSync(checkpointPath)).toBe(true);\n\n const saved = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));\n expect(saved.workingOn).toBe('c');\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('flush writes immediately and cancels the pending debounce', async () => {\n vi.useFakeTimers();\n const { checkpoint, flush } = await loadCheckpointModule();\n\n const vaultPath = makeTempVaultDir();\n try {\n const checkpointPath = path.join(vaultPath, '.clawvault', 'last-checkpoint.json');\n\n await checkpoint({ vaultPath, workingOn: 'soon' });\n const flushed = await flush();\n\n expect(flushed?.workingOn).toBe('soon');\n expect(fs.existsSync(checkpointPath)).toBe(true);\n const mtime = fs.statSync(checkpointPath).mtimeMs;\n\n await vi.advanceTimersByTimeAsync(2000);\n expect(fs.statSync(checkpointPath).mtimeMs).toBe(mtime);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('writes urgent checkpoints immediately and triggers a wake', async () => {\n execFileSyncMock.mockReturnValue('');\n const { checkpoint, checkDirtyDeath, clearDirtyFlag } = await loadCheckpointModule();\n\n const vaultPath = makeTempVaultDir();\n try {\n const checkpointPath = path.join(vaultPath, '.clawvault', 'last-checkpoint.json');\n const flagPath = path.join(vaultPath, '.clawvault', 'dirty-death.flag');\n\n const data = await checkpoint({ vaultPath, workingOn: 'urgent', urgent: true });\n\n expect(data.urgent).toBe(true);\n expect(fs.existsSync(checkpointPath)).toBe(true);\n expect(fs.existsSync(flagPath)).toBe(true);\n expect(execFileSyncMock).toHaveBeenCalledWith(\n 'openclaw',\n expect.arrayContaining(['gateway', 'wake', '--mode', 'now']),\n expect.objectContaining({ stdio: 'inherit' })\n );\n\n const deathInfo = await checkDirtyDeath(vaultPath);\n expect(deathInfo.died).toBe(true);\n expect(deathInfo.deathTime).toBeTruthy();\n\n await clearDirtyFlag(vaultPath);\n expect(fs.existsSync(flagPath)).toBe(false);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('uses env session details and persists startedAt', async () => {\n const { setSessionState, checkpoint } = await loadCheckpointModule();\n\n const vaultPath = makeTempVaultDir();\n try {\n await setSessionState(vaultPath, {\n sessionId: 'session-1',\n sessionKey: 'file-key',\n model: 'file-model',\n tokenEstimate: 123\n });\n\n const sessionPath = path.join(vaultPath, '.clawvault', 'session-state.json');\n const savedState = JSON.parse(fs.readFileSync(sessionPath, 'utf-8'));\n expect(savedState.startedAt).toBeTruthy();\n\n process.env.OPENCLAW_SESSION_KEY = 'env-key';\n process.env.OPENCLAW_MODEL = 'env-model';\n process.env.OPENCLAW_TOKEN_ESTIMATE = '456';\n\n const data = await checkpoint({ vaultPath, workingOn: 'work' });\n expect(data.sessionKey).toBe('env-key');\n expect(data.model).toBe('env-model');\n expect(data.tokenEstimate).toBe(456);\n expect(data.sessionStartedAt).toBe(savedState.startedAt);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n});\n\n",485 "inputSchema": {},486 "outputSchema": null,487 "icons": null,488 "annotations": null,489 "meta": null,490 "execution": null491 },492 {493 "name": "template.ts",494 "title": null,495 "description": "Script: template.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport { buildTemplateVariables, renderTemplate, TemplateVariables } from '../lib/template-engine.js';\n\nconst VAULT_CONFIG_FILE = '.clawvault.json';\nconst TEMPLATE_EXTENSION = '.md';\n\nexport interface TemplateCommandContext {\n vaultPath?: string;\n cwd?: string;\n builtinDir?: string;\n}\n\nexport interface TemplateCreateOptions extends TemplateCommandContext {\n title?: string;\n type?: string;\n}\n\nexport interface TemplateAddOptions extends TemplateCommandContext {\n name: string;\n overwrite?: boolean;\n}\n\nfunction resolveBuiltinTemplatesDir(override?: string): string | null {\n if (override) {\n const resolved = path.resolve(override);\n return fs.existsSync(resolved) ? resolved : null;\n }\n\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(moduleDir, '../templates'),\n path.resolve(moduleDir, '../../templates')\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {\n return candidate;\n }\n }\n\n return null;\n}\n\nfunction findVaultRoot(start: string): string | null {\n let current = path.resolve(start);\n while (true) {\n if (fs.existsSync(path.join(current, VAULT_CONFIG_FILE))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nfunction resolveVaultPath(options: TemplateCommandContext): string | null {\n if (options.vaultPath) {\n return path.resolve(options.vaultPath);\n }\n\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n return path.resolve(envPath);\n }\n\n const cwd = options.cwd ?? process.cwd();\n return findVaultRoot(cwd);\n}\n\nfunction normalizeTemplateName(name: string): string {\n const base = path.basename(name, path.extname(name));\n return base.trim();\n}\n\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .trim();\n}\n\nfunction listTemplateFiles(dir: string, ignore?: Set<string>): Map<string, string> {\n const entries = new Map<string, string>();\n if (!fs.existsSync(dir)) return entries;\n\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(TEMPLATE_EXTENSION)) continue;\n const name = normalizeTemplateName(entry.name);\n if (!name) continue;\n if (ignore?.has(name)) continue;\n entries.set(name, path.join(dir, entry.name));\n }\n\n return entries;\n}\n\nfunction buildTemplateIndex(options: TemplateCommandContext): Map<string, string> {\n const index = new Map<string, string>();\n const builtinDir = resolveBuiltinTemplatesDir(options.builtinDir);\n if (builtinDir) {\n const ignore = new Set(['daily']);\n for (const [name, filePath] of listTemplateFiles(builtinDir, ignore)) {\n index.set(name, filePath);\n }\n }\n\n const vaultPath = resolveVaultPath(options);\n if (vaultPath) {\n const vaultTemplatesDir = path.join(vaultPath, 'templates');\n for (const [name, filePath] of listTemplateFiles(vaultTemplatesDir)) {\n index.set(name, filePath);\n }\n }\n\n return index;\n}\n\nexport function listTemplates(options: TemplateCommandContext = {}): string[] {\n const index = buildTemplateIndex(options);\n return [...index.keys()].sort();\n}\n\nexport function createFromTemplate(\n name: string,\n options: TemplateCreateOptions = {}\n): { outputPath: string; templatePath: string; variables: TemplateVariables } {\n const templateName = normalizeTemplateName(name);\n if (!templateName) {\n throw new Error('Template name is required.');\n }\n\n const index = buildTemplateIndex(options);\n const templatePath = index.get(templateName);\n if (!templatePath) {\n const available = [...index.keys()].sort();\n const hint = available.length > 0 ? ` Available: ${available.join(', ')}` : '';\n throw new Error(`Template not found: ${templateName}.${hint}`);\n }\n\n const raw = fs.readFileSync(templatePath, 'utf-8');\n const now = new Date();\n const date = now.toISOString().split('T')[0];\n const type = options.type ?? templateName;\n const title = options.title ?? `${type} ${date}`.trim();\n\n const variables = buildTemplateVariables({ title, type, date }, now);\n const rendered = renderTemplate(raw, variables);\n\n const cwd = options.cwd ?? process.cwd();\n const slug = slugify(title) || slugify(templateName) || `template-${date}`;\n const outputPath = path.join(cwd, `${slug}${TEMPLATE_EXTENSION}`);\n\n if (fs.existsSync(outputPath)) {\n throw new Error(`File already exists: ${outputPath}`);\n }\n\n fs.writeFileSync(outputPath, rendered);\n return { outputPath, templatePath, variables };\n}\n\nexport function addTemplate(\n file: string,\n options: TemplateAddOptions\n): { templatePath: string; name: string } {\n const name = normalizeTemplateName(options.name);\n if (!name) {\n throw new Error('Template name is required.');\n }\n\n const vaultPath = resolveVaultPath(options);\n if (!vaultPath) {\n throw new Error('No vault found. Set CLAWVAULT_PATH or use --vault.');\n }\n\n const cwd = options.cwd ?? process.cwd();\n const sourcePath = path.resolve(cwd, file);\n if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isFile()) {\n throw new Error(`Template file not found: ${sourcePath}`);\n }\n\n const templatesDir = path.join(vaultPath, 'templates');\n fs.mkdirSync(templatesDir, { recursive: true });\n\n const targetPath = path.join(templatesDir, `${name}${TEMPLATE_EXTENSION}`);\n if (fs.existsSync(targetPath) && !options.overwrite) {\n throw new Error(`Template already exists: ${targetPath}`);\n }\n\n fs.copyFileSync(sourcePath, targetPath);\n return { templatePath: targetPath, name };\n}\n",496 "inputSchema": {},497 "outputSchema": null,498 "icons": null,499 "annotations": null,500 "meta": null,501 "execution": null502 },503 {504 "name": "repair-session.ts",505 "title": null,506 "description": "Script: repair-session.ts. Code:\n/**\n * repair-session command - Repair corrupted OpenClaw session transcripts\n * \n * Fixes issues like:\n * - Aborted tool calls with partial JSON\n * - Orphaned tool_result messages referencing non-existent tool_use IDs\n * - Broken parent chain references\n */\n\nimport * as fs from 'fs';\nimport {\n listAgents,\n findMainSession,\n findSessionById,\n getSessionFilePath,\n type SessionInfo\n} from '../lib/session-utils.js';\n\nimport {\n analyzeSession,\n repairSession,\n type RepairResult\n} from '../lib/session-repair.js';\n\nexport interface RepairSessionOptions {\n sessionId?: string;\n agentId?: string;\n backup?: boolean;\n dryRun?: boolean;\n}\n\n/**\n * Resolve the session to repair\n */\nexport function resolveSession(options: RepairSessionOptions): SessionInfo | null {\n const { sessionId, agentId } = options;\n \n // If we have both session ID and agent ID, look up directly\n if (sessionId && agentId) {\n return findSessionById(agentId, sessionId);\n }\n \n // If we only have session ID, search all agents\n if (sessionId) {\n const agents = listAgents();\n for (const agent of agents) {\n const session = findSessionById(agent, sessionId);\n if (session) return session;\n }\n return null;\n }\n \n // If we only have agent ID, get main session\n if (agentId) {\n return findMainSession(agentId);\n }\n \n // Default: try to find a configured agent from environment\n const defaultAgent = process.env.OPENCLAW_AGENT_ID || 'clawdious';\n return findMainSession(defaultAgent);\n}\n\n/**\n * Format repair result for CLI output\n */\nexport function formatRepairResult(result: RepairResult, options: { dryRun?: boolean } = {}): string {\n const { dryRun = false } = options;\n const lines: string[] = [];\n \n lines.push(`Analyzing session: ${result.sessionId}`);\n lines.push('');\n \n if (result.corruptedEntries.length === 0) {\n lines.push('\u2705 No corruption detected. Session is clean.');\n return lines.join('\\n');\n }\n \n if (dryRun) {\n lines.push(`Found ${result.corruptedEntries.length} corrupted entries:`);\n } else {\n lines.push(`Found and fixed ${result.corruptedEntries.length} corrupted entries:`);\n }\n \n for (const entry of result.corruptedEntries) {\n const prefix = entry.type === 'aborted_tool_use' ? 'Aborted tool_use' : 'Orphaned tool_result';\n lines.push(` - Line ${entry.lineNumber}: ${prefix} (id: ${entry.toolUseId})`);\n }\n \n if (result.parentRelinks.length > 0) {\n lines.push('');\n if (dryRun) {\n lines.push(`Would relink ${result.parentRelinks.length} parent reference(s):`);\n } else {\n lines.push(`Relinked ${result.parentRelinks.length} parent reference(s):`);\n }\n for (const relink of result.parentRelinks.slice(0, 5)) {\n lines.push(` - Line ${relink.lineNumber}: parentId ${relink.oldParentId.slice(0, 8)}\u2026 \u2192 ${relink.newParentId === 'null' ? 'null' : relink.newParentId.slice(0, 8)}\u2026`);\n }\n if (result.parentRelinks.length > 5) {\n lines.push(` ... and ${result.parentRelinks.length - 5} more`);\n }\n }\n \n lines.push('');\n \n if (dryRun) {\n lines.push(`Would remove ${result.removedCount} entries, relink ${result.relinkedCount} parent references.`);\n } else {\n lines.push(`\u2705 Session repaired: removed ${result.removedCount} entries, relinked ${result.relinkedCount} parent references`);\n if (result.backupPath) {\n const backupName = result.backupPath.split('/').pop();\n lines.push(`Backup saved: ${backupName}`);\n }\n }\n \n return lines.join('\\n');\n}\n\n/**\n * Main repair-session command handler\n */\nexport async function repairSessionCommand(options: RepairSessionOptions): Promise<RepairResult> {\n const { backup = true, dryRun = false } = options;\n \n const session = resolveSession(options);\n \n if (!session) {\n throw new Error(\n options.sessionId\n ? `Session not found: ${options.sessionId}`\n : options.agentId\n ? `No main session found for agent: ${options.agentId}`\n : 'No session found. Specify --session or --agent.'\n );\n }\n \n if (!fs.existsSync(session.filePath)) {\n throw new Error(`Session file not found: ${session.filePath}`);\n }\n \n if (dryRun) {\n return analyzeSession(session.filePath);\n }\n \n return repairSession(session.filePath, { backup, dryRun: false });\n}\n\n/**\n * List available sessions for an agent (for --list flag)\n */\nexport function listAgentSessions(agentId?: string): string {\n const agents = agentId ? [agentId] : listAgents();\n const lines: string[] = [];\n \n if (agents.length === 0) {\n return 'No agents found in ~/.openclaw/agents/';\n }\n \n for (const agent of agents) {\n const mainSession = findMainSession(agent);\n if (mainSession) {\n lines.push(`${agent}:`);\n lines.push(` Main session: ${mainSession.sessionId}`);\n lines.push(` File: ${mainSession.filePath}`);\n if (mainSession.updatedAt) {\n const date = new Date(mainSession.updatedAt);\n lines.push(` Updated: ${date.toISOString()}`);\n }\n lines.push('');\n }\n }\n \n if (lines.length === 0) {\n return agentId\n ? `No sessions found for agent: ${agentId}`\n : 'No sessions found.';\n }\n \n return lines.join('\\n');\n}\n",507 "inputSchema": {},508 "outputSchema": null,509 "icons": null,510 "annotations": null,511 "meta": null,512 "execution": null513 },514 {515 "name": "doctor.test.ts",516 "title": null,517 "description": "Script: doctor.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { hasQmdMock, scanVaultLinksMock } = vi.hoisted(() => ({\n hasQmdMock: vi.fn(),\n scanVaultLinksMock: vi.fn()\n}));\n\nlet mockStats = { documents: 0, categories: {} as Record<string, number> };\nlet mockDocuments: Array<{\n id: string;\n path: string;\n category: string;\n title: string;\n content: string;\n frontmatter: Record<string, unknown>;\n links: string[];\n tags: string[];\n modified: Date;\n}> = [];\nlet mockHandoffs: typeof mockDocuments = [];\nlet mockInbox: typeof mockDocuments = [];\n\nvi.mock('../lib/search.js', async () => {\n const actual = await vi.importActual<typeof import('../lib/search.js')>('../lib/search.js');\n return {\n ...actual,\n hasQmd: hasQmdMock\n };\n});\n\nvi.mock('../lib/backlinks.js', () => ({\n scanVaultLinks: scanVaultLinksMock\n}));\n\nvi.mock('../lib/vault.js', () => ({\n ClawVault: class {\n private vaultPath: string;\n\n constructor(vaultPath: string) {\n this.vaultPath = vaultPath;\n }\n\n async load(): Promise<void> {\n return;\n }\n\n async stats(): Promise<{ documents: number; categories: Record<string, number> }> {\n return mockStats;\n }\n\n async list(category?: string) {\n if (category === 'handoffs') return mockHandoffs;\n if (category === 'inbox') return mockInbox;\n if (category) return [];\n return mockDocuments;\n }\n\n getPath(): string {\n return this.vaultPath;\n }\n\n getQmdCollection(): string {\n return 'vault';\n }\n },\n findVault: async () => null\n}));\n\nimport { doctor } from './doctor.js';\n\nfunction makeDoc(category: string, modified: Date) {\n return {\n id: `${category}/doc`,\n path: `/tmp/${category}/doc.md`,\n category,\n title: 'doc',\n content: '',\n frontmatter: {},\n links: [],\n tags: [],\n modified\n };\n}\n\nfunction makeTempDir(prefix: string): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), prefix));\n}\n\nconst envSnapshot = {\n HOME: process.env.HOME,\n SHELL: process.env.SHELL\n};\n\nafterEach(() => {\n vi.clearAllMocks();\n process.env.HOME = envSnapshot.HOME;\n process.env.SHELL = envSnapshot.SHELL;\n});\n\ndescribe('doctor', () => {\n it('reports when qmd is unavailable', async () => {\n hasQmdMock.mockReturnValue(false);\n const report = await doctor('/tmp/vault');\n const qmdCheck = report.checks.find(check => check.label === 'qmd installed');\n expect(qmdCheck?.status).toBe('error');\n expect(report.errors).toBeGreaterThan(0);\n });\n\n it('warns on stale handoff/checkpoint and backlog', async () => {\n hasQmdMock.mockReturnValue(true);\n scanVaultLinksMock.mockReturnValue({\n backlinks: new Map(),\n orphans: Array.from({ length: 25 }, () => ({ source: 'a', target: 'b' })),\n linkCount: 30\n });\n\n const vaultPath = makeTempDir('clawvault-doctor-');\n const homePath = makeTempDir('clawvault-home-');\n const clawvaultDir = path.join(vaultPath, '.clawvault');\n fs.mkdirSync(clawvaultDir, { recursive: true });\n const checkpointTime = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString();\n fs.writeFileSync(\n path.join(clawvaultDir, 'last-checkpoint.json'),\n JSON.stringify({ timestamp: checkpointTime }, null, 2)\n );\n\n process.env.HOME = homePath;\n process.env.SHELL = '/bin/bash';\n fs.writeFileSync(path.join(homePath, '.bashrc'), 'export CLAWVAULT_PATH=\"/tmp/vault\"');\n\n mockStats = { documents: 10, categories: { inbox: 6 } };\n mockDocuments = [makeDoc('projects', new Date())];\n mockHandoffs = [makeDoc('handoffs', new Date(Date.now() - 3 * 24 * 60 * 60 * 1000))];\n mockInbox = Array.from({ length: 6 }, () => makeDoc('inbox', new Date()));\n\n try {\n const report = await doctor(vaultPath);\n const warnings = report.checks.filter(check => check.status === 'warn').map(check => check.label);\n expect(warnings).toEqual(expect.arrayContaining([\n 'recent handoff',\n 'checkpoint freshness',\n 'orphan links',\n 'inbox backlog'\n ]));\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n fs.rmSync(homePath, { recursive: true, force: true });\n }\n });\n});\n",518 "inputSchema": {},519 "outputSchema": null,520 "icons": null,521 "annotations": null,522 "meta": null,523 "execution": null524 },525 {526 "name": "wake.ts",527 "title": null,528 "description": "Script: wake.ts. Code:\nimport * as path from 'path';\nimport { ClawVault } from '../lib/vault.js';\nimport type { SessionRecap } from '../types.js';\nimport { clearDirtyFlag } from './checkpoint.js';\nimport { recover, type RecoveryInfo } from './recover.js';\n\nexport interface WakeOptions {\n vaultPath: string;\n handoffLimit?: number;\n brief?: boolean;\n}\n\nexport interface WakeResult {\n recovery: RecoveryInfo;\n recap: SessionRecap;\n recapMarkdown: string;\n summary: string;\n}\n\nconst DEFAULT_HANDOFF_LIMIT = 3;\n\nfunction formatSummaryItems(items: string[], maxItems: number = 2): string {\n const cleaned = items.map(item => item.trim()).filter(Boolean);\n if (cleaned.length === 0) return '';\n if (cleaned.length <= maxItems) return cleaned.join(', ');\n return `${cleaned.slice(0, maxItems).join(', ')} +${cleaned.length - maxItems} more`;\n}\n\nexport function buildWakeSummary(recovery: RecoveryInfo, recap: SessionRecap): string {\n if (recovery.checkpoint?.workingOn) {\n return recovery.checkpoint.workingOn;\n }\n\n const latestHandoff = recap.recentHandoffs[0];\n if (latestHandoff?.workingOn?.length) {\n return formatSummaryItems(latestHandoff.workingOn);\n }\n\n if (recap.activeProjects.length > 0) {\n return formatSummaryItems(recap.activeProjects);\n }\n\n return 'No recent work summary found.';\n}\n\nexport async function wake(options: WakeOptions): Promise<WakeResult> {\n const vaultPath = path.resolve(options.vaultPath);\n const recovery = await recover(vaultPath, { clearFlag: true });\n await clearDirtyFlag(vaultPath);\n\n const vault = new ClawVault(vaultPath);\n await vault.load();\n const recap = await vault.generateRecap({\n handoffLimit: options.handoffLimit ?? DEFAULT_HANDOFF_LIMIT,\n brief: options.brief ?? true\n });\n const summary = buildWakeSummary(recovery, recap);\n const recapMarkdown = vault.formatRecap(recap, { brief: options.brief ?? true });\n\n return {\n recovery,\n recap,\n recapMarkdown,\n summary\n };\n}\n",529 "inputSchema": {},530 "outputSchema": null,531 "icons": null,532 "annotations": null,533 "meta": null,534 "execution": null535 },536 {537 "name": "setup.ts",538 "title": null,539 "description": "Script: setup.ts. Code:\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { execFileSync } from 'child_process';\nimport { DEFAULT_CATEGORIES } from '../types.js';\nimport { hasQmd } from '../lib/search.js';\nconst CONFIG_FILE = '.clawvault.json';\nfunction resolveVaultTarget(): { vaultPath: string; source: string; existed: boolean } {\n const envPath = process.env.CLAWVAULT_PATH?.trim();\n const home = os.homedir();\n \n // If CLAWVAULT_PATH is set, always use it (create if needed)\n if (envPath) {\n const vaultPath = path.resolve(envPath);\n return { vaultPath, source: 'CLAWVAULT_PATH', existed: fs.existsSync(vaultPath) };\n }\n \n // Otherwise check for existing vaults in priority order\n const candidates = [\n { vaultPath: path.join(home, '.openclaw', 'workspace', 'memory'), source: 'OpenClaw default' },\n { vaultPath: path.resolve(process.cwd(), 'memory'), source: './memory' },\n { vaultPath: path.join(home, 'memory'), source: '~/memory' }\n ];\n \n for (const candidate of candidates) {\n if (fs.existsSync(candidate.vaultPath)) {\n return { ...candidate, existed: true };\n }\n }\n \n // Default to OpenClaw path for new vaults\n const fallback = candidates[0];\n return { ...fallback, existed: false };\n}\nfunction ensureVaultStructure(vaultPath: string): boolean {\n fs.mkdirSync(vaultPath, { recursive: true });\n for (const category of DEFAULT_CATEGORIES) {\n fs.mkdirSync(path.join(vaultPath, category), { recursive: true });\n }\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (fs.existsSync(configPath)) return false;\n const now = new Date().toISOString();\n const name = path.basename(vaultPath);\n const meta = {\n name,\n version: '1.0.0',\n created: now,\n lastUpdated: now,\n categories: DEFAULT_CATEGORIES,\n documentCount: 0,\n qmdCollection: name,\n qmdRoot: vaultPath\n };\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n return true;\n}\nfunction getQmdConfig(vaultPath: string): { collection: string; root: string } {\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n try {\n const meta = JSON.parse(fs.readFileSync(configPath, 'utf-8')) as {\n name?: string;\n qmdCollection?: string;\n qmdRoot?: string;\n };\n return {\n collection: meta.qmdCollection || meta.name || path.basename(vaultPath),\n root: meta.qmdRoot || vaultPath\n };\n } catch {\n return { collection: path.basename(vaultPath), root: vaultPath };\n }\n }\n return { collection: path.basename(vaultPath), root: vaultPath };\n}\nexport async function setupCommand(): Promise<void> {\n const target = resolveVaultTarget();\n if (target.existed && !fs.statSync(target.vaultPath).isDirectory()) {\n throw new Error(`Vault path is not a directory: ${target.vaultPath}`);\n }\n if (!target.existed) fs.mkdirSync(target.vaultPath, { recursive: true });\n console.log(`${target.existed ? 'Found' : 'Created'} vault path (${target.source}): ${target.vaultPath}`);\n const initialized = ensureVaultStructure(target.vaultPath);\n console.log(initialized ? 'Initialized vault structure.' : 'Vault structure already present.');\n console.log('\\nTip: add this to your shell config:');\n console.log(` export CLAWVAULT_PATH=\"${target.vaultPath}\"`);\n if (hasQmd()) {\n const { collection, root } = getQmdConfig(target.vaultPath);\n try {\n execFileSync('qmd', ['collection', 'add', root, '--name', collection, '--mask', '**/*.md'], {\n stdio: 'ignore'\n });\n console.log(`qmd collection ready: ${collection}`);\n } catch {\n console.log('qmd collection already exists or could not be created.');\n }\n } else {\n console.log('qmd not found; skipping collection setup.');\n }\n}\n",540 "inputSchema": {},541 "outputSchema": null,542 "icons": null,543 "annotations": null,544 "meta": null,545 "execution": null546 },547 {548 "name": "shell-init.test.ts",549 "title": null,550 "description": "Script: shell-init.test.ts. Code:\nimport { describe, expect, it } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { shellInit } from './shell-init.js';\n\nfunction makeTempDir(prefix: string): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), prefix));\n}\n\ndescribe('shellInit', () => {\n it('uses CLAWVAULT_PATH from env when provided', () => {\n const output = shellInit({\n env: { CLAWVAULT_PATH: '/tmp/vault' } as NodeJS.ProcessEnv,\n cwd: '/'\n });\n expect(output).toContain(\"export CLAWVAULT_PATH='/tmp/vault'\");\n expect(output).toContain(\"alias cvwake='clawvault wake'\");\n expect(output).toContain(\"alias cvsleep='clawvault sleep'\");\n expect(output).toContain(\"alias cvcheck='clawvault doctor'\");\n });\n\n it('detects a vault path from cwd when env is empty', () => {\n const dir = makeTempDir('clawvault-shell-');\n try {\n fs.writeFileSync(path.join(dir, '.clawvault.json'), '{}');\n const output = shellInit({\n env: {} as NodeJS.ProcessEnv,\n cwd: dir\n });\n expect(output).toContain(`export CLAWVAULT_PATH='${dir}'`);\n } finally {\n fs.rmSync(dir, { recursive: true, force: true });\n }\n });\n});\n",551 "inputSchema": {},552 "outputSchema": null,553 "icons": null,554 "annotations": null,555 "meta": null,556 "execution": null557 },558 {559 "name": "entities.ts",560 "title": null,561 "description": "Script: entities.ts. Code:\nimport { buildEntityIndex } from '../lib/entity-index.js';\nimport { getVaultPath } from '../lib/config.js';\n\ninterface EntitiesOptions {\n json?: boolean;\n}\n\nexport async function entitiesCommand(options: EntitiesOptions): Promise<void> {\n const vaultPath = getVaultPath();\n const index = buildEntityIndex(vaultPath);\n \n if (options.json) {\n const output: Record<string, string[]> = {};\n for (const [path, entry] of index.byPath) {\n output[path] = entry.aliases;\n }\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n \n // Group by folder\n const byFolder: Record<string, Array<{ path: string; aliases: string[] }>> = {};\n \n for (const [path, entry] of index.byPath) {\n const folder = path.split('/')[0];\n if (!byFolder[folder]) byFolder[folder] = [];\n byFolder[folder].push({ path, aliases: entry.aliases });\n }\n \n console.log('\ud83d\udcda Linkable Entities\\n');\n \n for (const [folder, entities] of Object.entries(byFolder)) {\n console.log(`## ${folder}/`);\n for (const entity of entities) {\n const name = entity.path.split('/')[1];\n const otherAliases = entity.aliases.filter(a => a.toLowerCase() !== name.toLowerCase());\n if (otherAliases.length > 0) {\n console.log(` - ${name} (${otherAliases.join(', ')})`);\n } else {\n console.log(` - ${name}`);\n }\n }\n console.log();\n }\n \n console.log(`Total: ${index.byPath.size} entities, ${index.entries.size} linkable aliases`);\n}\n",562 "inputSchema": {},563 "outputSchema": null,564 "icons": null,565 "annotations": null,566 "meta": null,567 "execution": null568 },569 {570 "name": "shell-init.ts",571 "title": null,572 "description": "Script: shell-init.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nfunction detectVaultPath(startPath: string): string | null {\n let current = path.resolve(startPath);\n while (true) {\n const configPath = path.join(current, '.clawvault.json');\n if (fs.existsSync(configPath)) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nexport interface ShellInitOptions {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n}\n\nexport function shellInit(options: ShellInitOptions = {}): string {\n const env = options.env ?? process.env;\n const cwd = options.cwd ?? process.cwd();\n const detected = env.CLAWVAULT_PATH || detectVaultPath(cwd);\n\n const lines: string[] = [];\n lines.push('# ClawVault shell integration');\n\n if (detected) {\n lines.push('if [ -z \"$CLAWVAULT_PATH\" ]; then');\n lines.push(` export CLAWVAULT_PATH=${shellQuote(path.resolve(detected))}`);\n lines.push('fi');\n } else {\n lines.push('# Set CLAWVAULT_PATH to your vault directory:');\n lines.push('# export CLAWVAULT_PATH=\"/path/to/vault\"');\n }\n\n lines.push(\"alias cvwake='clawvault wake'\");\n lines.push(\"alias cvsleep='clawvault sleep'\");\n lines.push(\"alias cvcheck='clawvault doctor'\");\n\n return lines.join('\\n');\n}\n",573 "inputSchema": {},574 "outputSchema": null,575 "icons": null,576 "annotations": null,577 "meta": null,578 "execution": null579 },580 {581 "name": "types.ts",582 "title": null,583 "description": "Script: types.ts. Code:\n/**\n * ClawVault Types - The elephant's memory structure\n */\n\nexport interface VaultConfig {\n /** Root path of the vault */\n path: string;\n /** Name of the vault */\n name: string;\n /** Categories to create on init */\n categories: string[];\n /** qmd collection name (defaults to vault name if not set) */\n qmdCollection?: string;\n /** Root path for qmd collection (defaults to vault path) */\n qmdRoot?: string;\n /** Custom templates path (optional) */\n templatesPath?: string;\n}\n\nexport interface VaultMeta {\n name: string;\n version: string;\n created: string;\n lastUpdated: string;\n categories: string[];\n documentCount: number;\n /** qmd collection name (defaults to vault name if not set) */\n qmdCollection?: string;\n /** Root path for qmd collection (defaults to vault path) */\n qmdRoot?: string;\n}\n\nexport interface Document {\n /** Unique ID (relative path without extension) */\n id: string;\n /** Full file path */\n path: string;\n /** Category (folder name) */\n category: string;\n /** Document title */\n title: string;\n /** Raw content */\n content: string;\n /** Frontmatter metadata */\n frontmatter: Record<string, unknown>;\n /** Extracted wiki-links [[like-this]] */\n links: string[];\n /** Tags extracted from content */\n tags: string[];\n /** Last modified timestamp */\n modified: Date;\n}\n\nexport interface SearchResult {\n /** Document that matched */\n document: Document;\n /** Relevance score (0-1) */\n score: number;\n /** Matching snippet */\n snippet: string;\n /** Which terms matched */\n matchedTerms: string[];\n}\n\nexport interface SearchOptions {\n /** Max results to return */\n limit?: number;\n /** Minimum score threshold (0-1) */\n minScore?: number;\n /** Filter by category */\n category?: string;\n /** Filter by tags */\n tags?: string[];\n /** Include full content in results */\n fullContent?: boolean;\n}\n\nexport interface StoreOptions {\n /** Category to store in */\n category: string;\n /** Document title (used for filename) */\n title: string;\n /** Content body */\n content: string;\n /** Frontmatter metadata */\n frontmatter?: Record<string, unknown>;\n /** Override existing file */\n overwrite?: boolean;\n /** Trigger qmd update after storing */\n qmdUpdate?: boolean;\n /** Trigger qmd embed after storing (implies qmdUpdate) */\n qmdEmbed?: boolean;\n}\n\nexport interface SyncOptions {\n /** Target directory to sync to */\n target: string;\n /** Delete files in target not in source */\n deleteOrphans?: boolean;\n /** Dry run - don't actually sync */\n dryRun?: boolean;\n}\n\nexport interface SyncResult {\n copied: string[];\n deleted: string[];\n unchanged: string[];\n errors: string[];\n}\n\nexport type Category = \n | 'preferences'\n | 'decisions'\n | 'patterns'\n | 'people'\n | 'projects'\n | 'goals'\n | 'transcripts'\n | 'inbox'\n | 'templates'\n | 'facts'\n | 'feelings'\n | 'lessons'\n | 'commitments'\n | 'handoffs'\n | string;\n\nexport const DEFAULT_CATEGORIES: Category[] = [\n 'preferences',\n 'decisions',\n 'patterns',\n 'people',\n 'projects',\n 'goals',\n 'transcripts',\n 'inbox',\n 'templates'\n];\n\n/**\n * Memory Type Taxonomy (Benthic's 8 categories)\n * Knowing WHAT KIND of thing helps you know WHERE to put it\n */\nexport type MemoryType = \n | 'fact' // Raw information, data points\n | 'feeling' // Emotional states, reactions, moods\n | 'decision' // Choices made with reasoning\n | 'lesson' // What I learned, insights, patterns\n | 'commitment' // Promises, goals, obligations\n | 'preference' // Likes, dislikes, how I want things\n | 'relationship'// People, connections, dynamics\n | 'project'; // Active work, ventures, ongoing efforts\n\nexport const MEMORY_TYPES: MemoryType[] = [\n 'fact', 'feeling', 'decision', 'lesson', \n 'commitment', 'preference', 'relationship', 'project'\n];\n\n/**\n * Memory type to category mapping\n */\nexport const TYPE_TO_CATEGORY: Record<MemoryType, Category> = {\n fact: 'facts',\n feeling: 'feelings',\n decision: 'decisions',\n lesson: 'lessons',\n commitment: 'commitments',\n preference: 'preferences',\n relationship: 'people',\n project: 'projects'\n};\n\n/**\n * Handoff document - bridges sessions\n */\nexport interface HandoffDocument {\n /** When this handoff was created */\n created: string;\n /** Session key or identifier */\n sessionKey?: string;\n /** What I was working on */\n workingOn: string[];\n /** What is currently blocked */\n blocked: string[];\n /** What comes next */\n nextSteps: string[];\n /** Emotional state/energy */\n feeling?: string;\n /** Key decisions made */\n decisions?: string[];\n /** Open questions */\n openQuestions?: string[];\n}\n\n/**\n * Session recap - who I was when I woke up\n */\nexport interface SessionRecap {\n /** When recap was generated */\n generated: string;\n /** Recent handoffs (last N) */\n recentHandoffs: HandoffDocument[];\n /** Active projects */\n activeProjects: string[];\n /** Pending commitments */\n pendingCommitments: string[];\n /** Recent decisions made */\n recentDecisions?: string[];\n /** Recent lessons learned */\n recentLessons: string[];\n /** Key relationships to remember */\n keyRelationships: string[];\n /** Current emotional arc */\n emotionalArc?: string;\n}\n\nexport const DEFAULT_CONFIG: Partial<VaultConfig> = {\n categories: DEFAULT_CATEGORIES\n};\n",584 "inputSchema": {},585 "outputSchema": null,586 "icons": null,587 "annotations": null,588 "meta": null,589 "execution": null590 },591 {592 "name": "index.ts",593 "title": null,594 "description": "Script: index.ts. Code:\n/**\n * ClawVault \ud83d\udc18 \u2014 An Elephant Never Forgets\n * \n * Structured memory system for AI agents with Obsidian-compatible markdown\n * and embedded semantic search.\n * \n * @example\n * ```typescript\n * import { ClawVault, createVault, findVault } from 'clawvault';\n * \n * // Create a new vault\n * const vault = await createVault('./my-memory');\n * \n * // Store a memory\n * await vault.store({\n * category: 'decisions',\n * title: 'Use ClawVault',\n * content: 'Decided to use ClawVault for memory management.'\n * });\n * \n * // Search memories\n * const results = await vault.find('memory management');\n * console.log(results);\n * ```\n */\n\nimport * as fs from 'fs';\n\n// Core exports\nexport { ClawVault, createVault, findVault } from './lib/vault.js';\nexport { setupCommand } from './commands/setup.js';\nexport {\n SearchEngine,\n extractWikiLinks,\n extractTags,\n hasQmd,\n qmdUpdate,\n qmdEmbed,\n QmdUnavailableError,\n QMD_INSTALL_COMMAND,\n QMD_INSTALL_URL\n} from './lib/search.js';\n\nexport {\n renderTemplate,\n buildTemplateVariables\n} from './lib/template-engine.js';\nexport type { TemplateVariables } from './lib/template-engine.js';\n\n// Type exports\nexport type {\n VaultConfig,\n VaultMeta,\n Document,\n SearchResult,\n SearchOptions,\n StoreOptions,\n SyncOptions,\n SyncResult,\n Category,\n MemoryType,\n HandoffDocument,\n SessionRecap\n} from './types.js';\n\nexport { DEFAULT_CATEGORIES, DEFAULT_CONFIG, MEMORY_TYPES, TYPE_TO_CATEGORY } from './types.js';\n\n// Version\nfunction readPackageVersion(): string {\n try {\n const pkgUrl = new URL('../package.json', import.meta.url);\n const pkg = JSON.parse(fs.readFileSync(pkgUrl, 'utf-8')) as { version?: string };\n return pkg.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nexport const VERSION = readPackageVersion();\n",595 "inputSchema": {},596 "outputSchema": null,597 "icons": null,598 "annotations": null,599 "meta": null,600 "execution": null601 },602 {603 "name": "clawvault.js",604 "title": null,605 "description": "Script: clawvault.js. Code:\n#!/usr/bin/env node\n\n/**\n * ClawVault CLI \ud83d\udc18\n * An elephant never forgets.\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { spawn } from 'child_process';\nimport {\n ClawVault,\n createVault,\n findVault,\n QmdUnavailableError,\n QMD_INSTALL_COMMAND\n} from '../dist/index.js';\n\nconst program = new Command();\n\nconst CLI_VERSION = (() => {\n try {\n const pkgUrl = new URL('../package.json', import.meta.url);\n const pkg = JSON.parse(fs.readFileSync(pkgUrl, 'utf-8'));\n return pkg.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n})();\n\n// Helper to get vault (required for most commands)\n// Checks: 1) explicit path, 2) CLAWVAULT_PATH env, 3) walk up from cwd\nasync function getVault(vaultPath) {\n // Explicit path takes priority\n if (vaultPath) {\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n return vault;\n }\n \n // Check environment variable\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n const vault = new ClawVault(path.resolve(envPath));\n await vault.load();\n return vault;\n }\n \n // Walk up from cwd\n const vault = await findVault();\n if (!vault) {\n console.error(chalk.red('Error: No ClawVault found. Run `clawvault init` first.'));\n console.log(chalk.dim('Tip: Set CLAWVAULT_PATH environment variable to your vault path'));\n process.exit(1);\n }\n return vault;\n}\n\nfunction resolveVaultPath(vaultPath) {\n if (vaultPath) {\n return path.resolve(vaultPath);\n }\n if (process.env.CLAWVAULT_PATH) {\n return path.resolve(process.env.CLAWVAULT_PATH);\n }\n let current = process.cwd();\n while (true) {\n if (fs.existsSync(path.join(current, '.clawvault.json'))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n console.error(chalk.red('Error: No ClawVault found. Run `clawvault init` first.'));\n console.log(chalk.dim('Tip: Set CLAWVAULT_PATH environment variable to your vault path'));\n process.exit(1);\n }\n current = parent;\n }\n}\n\nasync function runQmd(args) {\n return new Promise((resolve, reject) => {\n const proc = spawn('qmd', args, { stdio: 'inherit' });\n proc.on('close', (code) => {\n if (code === 0) resolve();\n else reject(new Error(`qmd exited with code ${code}`));\n });\n proc.on('error', (err) => {\n if (err?.code === 'ENOENT') {\n reject(new QmdUnavailableError());\n } else {\n reject(err);\n }\n });\n });\n}\n\nfunction printQmdMissing() {\n console.error(chalk.red('Error: ClawVault requires qmd.'));\n console.log(chalk.dim(`Install: ${QMD_INSTALL_COMMAND}`));\n}\n\nprogram\n .name('clawvault')\n .description('\ud83d\udc18 An elephant never forgets. Structured memory for AI agents.')\n .version(CLI_VERSION);\n\n// === INIT ===\nprogram\n .command('init [path]')\n .description('Initialize a new ClawVault')\n .option('-n, --name <name>', 'Vault name')\n .option('--qmd', 'Set up qmd semantic search collection')\n .option('--qmd-collection <name>', 'qmd collection name (defaults to vault name)')\n .action(async (vaultPath, options) => {\n const targetPath = vaultPath || '.';\n console.log(chalk.cyan(`\\n\ud83d\udc18 Initializing ClawVault at ${path.resolve(targetPath)}...\\n`));\n \n try {\n const vault = await createVault(targetPath, {\n name: options.name || path.basename(path.resolve(targetPath)),\n qmdCollection: options.qmdCollection\n });\n \n console.log(chalk.green('\u2713 Vault created'));\n console.log(chalk.dim(` Categories: ${vault.getCategories().join(', ')}`));\n\n // Always set up qmd collection (qmd is required)\n console.log(chalk.cyan('\\nSetting up qmd collection...'));\n try {\n await runQmd([\n 'collection',\n 'add',\n vault.getQmdRoot(),\n '--name',\n vault.getQmdCollection(),\n '--mask',\n '**/*.md'\n ]);\n console.log(chalk.green('\u2713 qmd collection created'));\n } catch (err) {\n // Collection might already exist\n console.log(chalk.yellow('\u26a0 qmd collection may already exist'));\n }\n \n console.log(chalk.green('\\n\u2705 ClawVault ready!\\n'));\n console.log(chalk.dim('Next steps:'));\n console.log(chalk.dim(' clawvault store --category inbox --title \"My note\" --content \"Hello world\"'));\n console.log(chalk.dim(' clawvault search \"hello\"'));\n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SETUP ===\nprogram\n .command('setup')\n .description('Auto-discover and configure a ClawVault')\n .action(async () => {\n try {\n const { setupCommand } = await import('../dist/commands/setup.js');\n await setupCommand();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === STORE ===\nprogram\n .command('store')\n .description('Store a new memory')\n .requiredOption('-c, --category <category>', 'Category (preferences, decisions, patterns, people, projects, goals, transcripts, inbox)')\n .requiredOption('-t, --title <title>', 'Document title')\n .option('--content <content>', 'Content body')\n .option('-f, --file <file>', 'Read content from file')\n .option('--stdin', 'Read content from stdin')\n .option('--overwrite', 'Overwrite if exists')\n .option('--no-index', 'Skip qmd index update (auto-updates by default)')\n .option('--embed', 'Also update qmd embeddings for vector search')\n .option('-v, --vault <path>', 'Vault path (default: find nearest)')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n \n let content = options.content || '';\n \n if (options.file) {\n content = fs.readFileSync(options.file, 'utf-8');\n } else if (options.stdin) {\n content = fs.readFileSync(0, 'utf-8');\n }\n \n const doc = await vault.store({\n category: options.category,\n title: options.title,\n content,\n overwrite: options.overwrite\n });\n \n console.log(chalk.green(`\u2713 Stored: ${doc.id}`));\n console.log(chalk.dim(` Path: ${doc.path}`));\n \n // Auto-update qmd index unless --no-index\n if (options.index !== false) {\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n if (options.embed) {\n await runQmd(collection ? ['embed', '-c', collection] : ['embed']);\n }\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === CAPTURE ===\nprogram\n .command('capture <note>')\n .description('Quick capture to inbox')\n .option('-t, --title <title>', 'Note title')\n .option('-v, --vault <path>', 'Vault path')\n .option('--no-index', 'Skip qmd index update')\n .action(async (note, options) => {\n try {\n const vault = await getVault(options.vault);\n const doc = await vault.capture(note, options.title);\n console.log(chalk.green(`\u2713 Captured: ${doc.id}`));\n \n // Auto-update qmd index unless --no-index\n if (options.index !== false) {\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SEARCH ===\nprogram\n .command('search <query>')\n .description('Search the vault via qmd (BM25)')\n .option('-n, --limit <n>', 'Max results', '10')\n .option('-c, --category <category>', 'Filter by category')\n .option('--tags <tags>', 'Filter by tags (comma-separated)')\n .option('--full', 'Include full content in results')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (query, options) => {\n try {\n const vault = await getVault(options.vault);\n \n const results = await vault.find(query, {\n limit: parseInt(options.limit),\n category: options.category,\n tags: options.tags?.split(',').map(t => t.trim()),\n fullContent: options.full\n });\n \n if (options.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n \n if (results.length === 0) {\n console.log(chalk.yellow('No results found.'));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83d\udd0d Found ${results.length} result(s) for \"${query}\":\\n`));\n \n for (const result of results) {\n const scoreBar = '\u2588'.repeat(Math.round(result.score * 10)).padEnd(10, '\u2591');\n console.log(chalk.green(`\ud83d\udcc4 ${result.document.title}`));\n console.log(chalk.dim(` ${result.document.category}/${result.document.id.split('/').pop()}`));\n console.log(chalk.dim(` Score: ${scoreBar} ${(result.score * 100).toFixed(0)}%`));\n if (result.snippet) {\n console.log(chalk.white(` ${result.snippet.split('\\n')[0].slice(0, 80)}...`));\n }\n console.log();\n }\n } catch (err) {\n if (err instanceof QmdUnavailableError) {\n printQmdMissing();\n process.exit(1);\n }\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === VSEARCH (qmd semantic search) ===\nprogram\n .command('vsearch <query>')\n .description('Semantic search via qmd (requires qmd installed)')\n .option('-n, --limit <n>', 'Max results', '5')\n .option('-c, --category <category>', 'Filter by category')\n .option('--tags <tags>', 'Filter by tags (comma-separated)')\n .option('--full', 'Include full content in results')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (query, options) => {\n try {\n const vault = await getVault(options.vault);\n \n const results = await vault.vsearch(query, {\n limit: parseInt(options.limit),\n category: options.category,\n tags: options.tags?.split(',').map(t => t.trim()),\n fullContent: options.full\n });\n \n if (options.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n \n if (results.length === 0) {\n console.log(chalk.yellow('No results found.'));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83e\udde0 Found ${results.length} result(s) for \"${query}\":\\n`));\n \n for (const result of results) {\n const scoreBar = '\u2588'.repeat(Math.round(result.score * 10)).padEnd(10, '\u2591');\n console.log(chalk.green(`\ud83d\udcc4 ${result.document.title}`));\n console.log(chalk.dim(` ${result.document.category}/${result.document.id.split('/').pop()}`));\n console.log(chalk.dim(` Score: ${scoreBar} ${(result.score * 100).toFixed(0)}%`));\n if (result.snippet) {\n console.log(chalk.white(` ${result.snippet.split('\\n')[0].slice(0, 80)}...`));\n }\n console.log();\n }\n } catch (err) {\n if (err instanceof QmdUnavailableError) {\n printQmdMissing();\n process.exit(1);\n }\n console.error(chalk.red(`Error: ${err.message}`));\n console.log(chalk.dim(`\\nTip: Install qmd: ${QMD_INSTALL_COMMAND}`));\n process.exit(1);\n }\n });\n\n// === LIST ===\nprogram\n .command('list [category]')\n .description('List documents')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (category, options) => {\n try {\n const vault = await getVault(options.vault);\n const docs = await vault.list(category);\n \n if (options.json) {\n console.log(JSON.stringify(docs.map(d => ({\n id: d.id,\n title: d.title,\n category: d.category,\n tags: d.tags,\n modified: d.modified\n })), null, 2));\n return;\n }\n \n if (docs.length === 0) {\n console.log(chalk.yellow('No documents found.'));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83d\udcda ${docs.length} document(s)${category ? ` in ${category}` : ''}:\\n`));\n \n // Group by category\n const grouped = {};\n for (const doc of docs) {\n grouped[doc.category] = grouped[doc.category] || [];\n grouped[doc.category].push(doc);\n }\n \n for (const [cat, catDocs] of Object.entries(grouped)) {\n console.log(chalk.yellow(`${cat}/`));\n for (const doc of catDocs) {\n console.log(chalk.dim(` - ${doc.title}`));\n }\n }\n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === GET ===\nprogram\n .command('get <id>')\n .description('Get a document by ID')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (id, options) => {\n try {\n const vault = await getVault(options.vault);\n const doc = await vault.get(id);\n \n if (!doc) {\n console.error(chalk.red(`Document not found: ${id}`));\n process.exit(1);\n }\n \n if (options.json) {\n console.log(JSON.stringify(doc, null, 2));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83d\udcc4 ${doc.title}\\n`));\n console.log(chalk.dim(`Category: ${doc.category}`));\n console.log(chalk.dim(`Path: ${doc.path}`));\n console.log(chalk.dim(`Tags: ${doc.tags.join(', ') || 'none'}`));\n console.log(chalk.dim(`Links: ${doc.links.join(', ') || 'none'}`));\n console.log(chalk.dim(`Modified: ${doc.modified.toISOString()}`));\n console.log(chalk.dim('---'));\n console.log(doc.content);\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === STATS ===\nprogram\n .command('stats')\n .description('Show vault statistics')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n const stats = await vault.stats();\n \n if (options.json) {\n console.log(JSON.stringify(stats, null, 2));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83d\udc18 ${vault.getName()} Stats\\n`));\n console.log(chalk.dim(`Path: ${vault.getPath()}`));\n console.log(`Documents: ${chalk.green(stats.documents)}`);\n console.log(`Links: ${chalk.blue(stats.links)}`);\n console.log(`Tags: ${chalk.yellow(stats.tags.length)}`);\n console.log();\n console.log(chalk.dim('By category:'));\n for (const [cat, count] of Object.entries(stats.categories)) {\n console.log(chalk.dim(` ${cat}: ${count}`));\n }\n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SYNC ===\nprogram\n .command('sync <target>')\n .description('Sync vault to another location (e.g., for Obsidian)')\n .option('--delete', 'Delete orphan files in target')\n .option('--dry-run', \"Show what would be synced without syncing\")\n .option('-v, --vault <path>', 'Vault path')\n .action(async (target, options) => {\n try {\n const vault = await getVault(options.vault);\n \n console.log(chalk.cyan(`\\n\ud83d\udd04 Syncing to ${target}...\\n`));\n \n const result = await vault.sync({\n target,\n deleteOrphans: options.delete,\n dryRun: options.dryRun\n });\n \n if (options.dryRun) {\n console.log(chalk.yellow('DRY RUN - no changes made\\n'));\n }\n \n if (result.copied.length > 0) {\n console.log(chalk.green(`Copied: ${result.copied.length} files`));\n for (const f of result.copied.slice(0, 5)) {\n console.log(chalk.dim(` + ${f}`));\n }\n if (result.copied.length > 5) {\n console.log(chalk.dim(` ... and ${result.copied.length - 5} more`));\n }\n }\n \n if (result.deleted.length > 0) {\n console.log(chalk.red(`Deleted: ${result.deleted.length} files`));\n }\n \n if (result.unchanged.length > 0) {\n console.log(chalk.dim(`Unchanged: ${result.unchanged.length} files`));\n }\n \n if (result.errors.length > 0) {\n console.log(chalk.red(`\\nErrors:`));\n for (const e of result.errors) {\n console.log(chalk.red(` ${e}`));\n }\n }\n \n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === REINDEX ===\nprogram\n .command('reindex')\n .description('Rebuild the search index')\n .option('-v, --vault <path>', 'Vault path')\n .option('--qmd', 'Also update qmd embeddings')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n \n console.log(chalk.cyan('\\n\ud83d\udd04 Reindexing...\\n'));\n \n const count = await vault.reindex();\n console.log(chalk.green(`\u2713 Indexed ${count} documents`));\n \n if (options.qmd) {\n console.log(chalk.cyan('Updating qmd embeddings...'));\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n console.log(chalk.green('\u2713 qmd updated'));\n }\n \n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === REMEMBER (type-based storage) ===\nprogram\n .command('remember <type> <title>')\n .description('Store a memory with type classification (fact|feeling|decision|lesson|commitment|preference|relationship|project)')\n .option('--content <content>', 'Content body')\n .option('-f, --file <file>', 'Read content from file')\n .option('--stdin', 'Read content from stdin')\n .option('-v, --vault <path>', 'Vault path')\n .option('--no-index', 'Skip qmd index update')\n .action(async (type, title, options) => {\n const validTypes = ['fact', 'feeling', 'decision', 'lesson', 'commitment', 'preference', 'relationship', 'project'];\n if (!validTypes.includes(type)) {\n console.error(chalk.red(`Invalid type: ${type}`));\n console.error(chalk.dim(`Valid types: ${validTypes.join(', ')}`));\n process.exit(1);\n }\n \n try {\n const vault = await getVault(options.vault);\n \n let content = options.content || '';\n if (options.file) {\n content = fs.readFileSync(options.file, 'utf-8');\n } else if (options.stdin) {\n content = fs.readFileSync(0, 'utf-8');\n }\n \n const doc = await vault.remember(type, title, content);\n console.log(chalk.green(`\u2713 Remembered (${type}): ${doc.id}`));\n \n // Auto-update qmd index unless --no-index\n if (options.index !== false) {\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === WAKE (session start) ===\nprogram\n .command('wake')\n .description('Start a session (recover + recap + summary)')\n .option('-n, --handoff-limit <n>', 'Number of recent handoffs to include', '3')\n .option('--full', 'Show full recap (default: brief)')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (options) => {\n try {\n const vaultPath = resolveVaultPath(options.vault);\n const { wake } = await import('../dist/commands/wake.js');\n const { formatRecoveryInfo } = await import('../dist/commands/recover.js');\n const result = await wake({\n vaultPath,\n handoffLimit: parseInt(options.handoffLimit),\n brief: !options.full\n });\n\n console.log(chalk.cyan('\\n\ud83c\udf05 ClawVault Wake\\n'));\n console.log(formatRecoveryInfo(result.recovery));\n console.log();\n console.log(chalk.cyan('Recap'));\n console.log(result.recapMarkdown.trim());\n console.log();\n console.log(chalk.green(`You were working on: ${result.summary}`));\n\n process.exitCode = result.recovery.died ? 1 : 0;\n } catch (err) {\n if (err instanceof QmdUnavailableError) {\n printQmdMissing();\n process.exit(1);\n }\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SLEEP (session end) ===\nprogram\n .command('sleep <summary>')\n .description('End a session with a handoff (and optional git commit)')\n .option('-n, --next <items>', 'Next steps (comma-separated)')\n .option('-b, --blocked <items>', 'Blocked items (comma-separated)')\n .option('-d, --decisions <items>', 'Key decisions made (comma-separated)')\n .option('-q, --questions <items>', 'Open questions (comma-separated)')\n .option('-f, --feeling <state>', 'Emotional/energy state')\n .option('-s, --session <key>', 'Session key')\n .option('--index', 'Update qmd index after handoff')\n .option('--no-git', 'Skip git commit prompt')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (summary, options) => {\n try {\n const vaultPath = resolveVaultPath(options.vault);\n const { sleep } = await import('../dist/commands/sleep.js');\n const result = await sleep({\n workingOn: summary,\n next: options.next,\n blocked: options.blocked,\n decisions: options.decisions,\n questions: options.questions,\n feeling: options.feeling,\n sessionKey: options.session,\n vaultPath,\n index: options.index,\n git: options.git\n });\n\n console.log(chalk.green(`\u2713 Handoff saved: ${result.document.id}`));\n console.log(chalk.dim(` Path: ${result.document.path}`));\n console.log(chalk.dim(` Working on: ${result.handoff.workingOn.join(', ')}`));\n if (result.handoff.nextSteps.length > 0) {\n console.log(chalk.dim(` Next: ${result.handoff.nextSteps.join(', ')}`));\n } else {\n console.log(chalk.dim(' Next: (none)'));\n }\n if (result.handoff.blocked.length > 0) {\n console.log(chalk.dim(` Blocked: ${result.handoff.blocked.join(', ')}`));\n } else {\n console.log(chalk.dim(' Blocked: (none)'));\n }\n if (result.handoff.decisions?.length) {\n console.log(chalk.dim(` Decisions: ${result.handoff.decisions.join(', ')}`));\n }\n if (result.handoff.openQuestions?.length) {\n console.log(chalk.dim(` Questions: ${result.handoff.openQuestions.join(', ')}`));\n }\n if (result.handoff.feeling) {\n console.log(chalk.dim(` Feeling: ${result.handoff.feeling}`));\n }\n if (options.index) {\n console.log(chalk.dim(' qmd: index updated'));\n }\n if (result.git) {\n if (result.git.committed) {\n console.log(chalk.green(`\u2713 Git commit created${result.git.message ? `: ${result.git.message}` : ''}`));\n } else if (result.git.skippedReason === 'clean') {\n console.log(chalk.dim(' Git: clean'));\n } else if (result.git.skippedReason === 'declined') {\n console.log(chalk.dim(' Git: commit skipped'));\n }\n }\n } catch (err) {\n if (err instanceof QmdUnavailableError) {\n printQmdMissing();\n process.exit(1);\n }\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === HANDOFF (session bridge) ===\nprogram\n .command('handoff')\n .description('Create a session handoff document')\n .requiredOption('-w, --working-on <items>', 'What I was working on (comma-separated)')\n .option('-b, --blocked <items>', 'What is blocked (comma-separated)')\n .option('-n, --next <items>', 'What comes next (comma-separated)')\n .option('-d, --decisions <items>', 'Key decisions made (comma-separated)')\n .option('-q, --questions <items>', 'Open questions (comma-separated)')\n .option('-f, --feeling <state>', 'Emotional/energy state')\n .option('-s, --session <key>', 'Session key')\n .option('-v, --vault <path>', 'Vault path')\n .option('--no-index', 'Skip qmd index update (auto-updates by default)')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n \n const handoff = {\n workingOn: options.workingOn.split(',').map(s => s.trim()),\n blocked: options.blocked ? options.blocked.split(',').map(s => s.trim()) : [],\n nextSteps: options.next ? options.next.split(',').map(s => s.trim()) : [],\n decisions: options.decisions ? options.decisions.split(',').map(s => s.trim()) : undefined,\n openQuestions: options.questions ? options.questions.split(',').map(s => s.trim()) : undefined,\n feeling: options.feeling,\n sessionKey: options.session\n };\n \n const doc = await vault.createHandoff(handoff);\n \n if (options.json) {\n console.log(JSON.stringify({ id: doc.id, path: doc.path, handoff }, null, 2));\n } else {\n console.log(chalk.green(`\u2713 Handoff created: ${doc.id}`));\n console.log(chalk.dim(` Path: ${doc.path}`));\n }\n \n // Auto-update qmd index unless --no-index\n if (options.index !== false) {\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === RECAP (session bootstrap) ===\nprogram\n .command('recap')\n .description('Generate a session recap - who I was (bootstrap hook)')\n .option('-n, --handoff-limit <n>', 'Number of recent handoffs to include', '3')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .option('--markdown', 'Output as markdown (default)')\n .option('--brief', 'Minimal output for token savings')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n \n const recap = await vault.generateRecap({\n handoffLimit: parseInt(options.handoffLimit),\n brief: options.brief\n });\n \n if (options.json) {\n console.log(JSON.stringify(recap, null, 2));\n return;\n }\n \n // Output as markdown (default)\n const md = vault.formatRecap(recap, { brief: options.brief });\n console.log(md);\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SHELL INIT ===\nprogram\n .command('shell-init')\n .description('Output shell integration for ClawVault')\n .action(async () => {\n try {\n const { shellInit } = await import('../dist/commands/shell-init.js');\n console.log(shellInit());\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === TEMPLATE ===\nconst template = program\n .command('template')\n .description('Manage templates');\n\ntemplate\n .command('list')\n .description('List available templates')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (options) => {\n try {\n const { listTemplates } = await import('../dist/commands/template.js');\n const templates = listTemplates({ vaultPath: options.vault });\n if (templates.length === 0) {\n console.log(chalk.yellow('No templates found.'));\n return;\n }\n console.log(chalk.cyan('\\n\ud83d\udcc4 Templates:\\n'));\n for (const name of templates) {\n console.log(`- ${name}`);\n }\n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\ntemplate\n .command('create <name>')\n .description('Create a file from a template')\n .option('-t, --title <title>', 'Document title')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (name, options) => {\n try {\n const { createFromTemplate } = await import('../dist/commands/template.js');\n const result = createFromTemplate(name, {\n title: options.title,\n vaultPath: options.vault\n });\n console.log(chalk.green(`\u2713 Created from template: ${name}`));\n console.log(chalk.dim(` Output: ${result.outputPath}`));\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\ntemplate\n .command('add <file>')\n .description('Add a custom template')\n .requiredOption('--name <name>', 'Template name')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (file, options) => {\n try {\n const { addTemplate } = await import('../dist/commands/template.js');\n const result = addTemplate(file, {\n name: options.name,\n vaultPath: options.vault\n });\n console.log(chalk.green(`\u2713 Template added: ${result.name}`));\n console.log(chalk.dim(` Path: ${result.templatePath}`));\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === DOCTOR (health check) ===\nprogram\n .command('doctor')\n .description('Check ClawVault setup health')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (options) => {\n try {\n const { doctor } = await import('../dist/commands/doctor.js');\n const report = await doctor(options.vault);\n\n console.log(chalk.cyan('\\n\ud83e\ude7a ClawVault Health Check\\n'));\n if (report.vaultPath) {\n console.log(chalk.dim(`Vault: ${report.vaultPath}`));\n console.log();\n }\n\n for (const check of report.checks) {\n const prefix = check.status === 'ok'\n ? chalk.green('\u2713')\n : check.status === 'warn'\n ? chalk.yellow('\u26a0')\n : chalk.red('\u2717');\n const detail = check.detail ? ` \u2014 ${check.detail}` : '';\n console.log(`${prefix} ${check.label}${detail}`);\n if (check.hint) {\n console.log(chalk.dim(` ${check.hint}`));\n }\n }\n\n const issues = report.warnings + report.errors;\n console.log();\n if (issues === 0) {\n console.log(chalk.green('\u2705 ClawVault is healthy!\\n'));\n } else {\n console.log(chalk.yellow(`\u26a0 ${issues} issue(s) found\\n`));\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === ENTITIES ===\nprogram\n .command('entities')\n .description('List all linkable entities in the vault')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { entitiesCommand } = await import('../dist/commands/entities.js');\n await entitiesCommand({ json: options.json });\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === LINK ===\nprogram\n .command('link [file]')\n .description('Auto-link entity mentions in markdown files')\n .option('--all', 'Link all files in vault')\n .option('--backlinks <file>', 'Show backlinks to a file')\n .option('--dry-run', 'Show what would be linked without changing files')\n .option('--orphans', 'List broken wiki-links')\n .option('--rebuild', 'Rebuild backlinks index')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (file, options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { linkCommand } = await import('../dist/commands/link.js');\n await linkCommand(file, {\n all: options.all,\n dryRun: options.dryRun,\n backlinks: options.backlinks,\n orphans: options.orphans,\n rebuild: options.rebuild\n });\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === CHECKPOINT ===\nprogram\n .command('checkpoint')\n .description('Quick state checkpoint for context death resilience')\n .option('--working-on <text>', 'What you are currently working on')\n .option('--focus <text>', 'Current focus area')\n .option('--blocked <text>', 'What is blocking progress')\n .option('--urgent', 'Trigger OpenClaw wake after checkpoint')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { checkpoint } = await import('../dist/commands/checkpoint.js');\n const data = await checkpoint({\n vaultPath: path.resolve(vaultPath),\n workingOn: options.workingOn,\n focus: options.focus,\n blocked: options.blocked,\n urgent: options.urgent\n });\n \n if (options.json) {\n console.log(JSON.stringify(data, null, 2));\n } else {\n console.log(chalk.green('\u2713 Checkpoint saved'));\n console.log(chalk.dim(` Timestamp: ${data.timestamp}`));\n if (data.workingOn) console.log(chalk.dim(` Working on: ${data.workingOn}`));\n if (data.focus) console.log(chalk.dim(` Focus: ${data.focus}`));\n if (data.blocked) console.log(chalk.dim(` Blocked: ${data.blocked}`));\n if (data.urgent) console.log(chalk.dim(' Urgent: yes'));\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === RECOVER ===\nprogram\n .command('recover')\n .description('Check for context death and recover state')\n .option('--clear', 'Clear the dirty death flag after recovery')\n .option('--verbose', 'Show full checkpoint and handoff content')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { recover, formatRecoveryInfo } = await import('../dist/commands/recover.js');\n const info = await recover(path.resolve(vaultPath), {\n clearFlag: options.clear,\n verbose: options.verbose\n });\n \n if (options.json) {\n console.log(JSON.stringify(info, null, 2));\n } else {\n console.log(formatRecoveryInfo(info, { verbose: options.verbose }));\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === STATUS ===\nprogram\n .command('status')\n .description('Show vault health and status')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n\n const { statusCommand } = await import('../dist/commands/status.js');\n await statusCommand(path.resolve(vaultPath), { json: options.json });\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === CLEAN-EXIT ===\nprogram\n .command('clean-exit')\n .description('Mark session as cleanly exited (clears dirty death flag)')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { cleanExit } = await import('../dist/commands/checkpoint.js');\n await cleanExit(path.resolve(vaultPath));\n console.log(chalk.green('\u2713 Clean exit recorded'));\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === REPAIR-SESSION ===\nprogram\n .command('repair-session')\n .description('Repair corrupted OpenClaw session transcripts')\n .option('-s, --session <id>', 'Session ID (defaults to current main session)')\n .option('-a, --agent <id>', 'Agent ID (defaults to configured agent)')\n .option('--backup', 'Create backup before repair (default: true)', true)\n .option('--no-backup', 'Skip backup creation')\n .option('--dry-run', 'Show what would be repaired without writing')\n .option('--list', 'List available sessions')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const {\n repairSessionCommand,\n formatRepairResult,\n listAgentSessions\n } = await import('../dist/commands/repair-session.js');\n \n // List mode\n if (options.list) {\n console.log(listAgentSessions(options.agent));\n return;\n }\n \n const result = await repairSessionCommand({\n sessionId: options.session,\n agentId: options.agent,\n backup: options.backup,\n dryRun: options.dryRun\n });\n \n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatRepairResult(result, { dryRun: options.dryRun }));\n }\n \n // Exit with code 1 if corruption was found but not fixed (dry-run)\n if (result.corruptedEntries.length > 0 && !result.repaired) {\n process.exit(1);\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// Parse and run\nprogram.parse();\n",606 "inputSchema": {},607 "outputSchema": null,608 "icons": null,609 "annotations": null,610 "meta": null,611 "execution": null612 },613 {614 "name": "handler.js",615 "title": null,616 "description": "Script: handler.js. Code:\n/**\n * ClawVault OpenClaw Hook\n * \n * Provides automatic context death resilience:\n * - gateway:startup \u2192 detect context death, inject recovery info\n * - command:new \u2192 auto-checkpoint before session reset\n * \n * SECURITY: Uses execFileSync (no shell) to prevent command injection\n */\n\nimport { execFileSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// Sanitize string for safe display (prevent prompt injection via control chars)\nfunction sanitizeForDisplay(str) {\n if (typeof str !== 'string') return '';\n // Remove control characters, limit length, escape markdown\n return str\n .replace(/[\\x00-\\x1f\\x7f]/g, '') // Remove control chars\n .replace(/[`*_~\\[\\]]/g, '\\\\$&') // Escape markdown\n .slice(0, 200); // Limit length\n}\n\n// Validate vault path - must be absolute and exist\nfunction validateVaultPath(vaultPath) {\n if (!vaultPath || typeof vaultPath !== 'string') return null;\n \n // Resolve to absolute path\n const resolved = path.resolve(vaultPath);\n \n // Must be absolute\n if (!path.isAbsolute(resolved)) return null;\n \n // Must exist and be a directory\n try {\n const stat = fs.statSync(resolved);\n if (!stat.isDirectory()) return null;\n } catch {\n return null;\n }\n \n // Must contain .clawvault.json\n const configPath = path.join(resolved, '.clawvault.json');\n if (!fs.existsSync(configPath)) return null;\n \n return resolved;\n}\n\n// Find vault by walking up directories\nfunction findVaultPath() {\n // Check env first\n if (process.env.CLAWVAULT_PATH) {\n return validateVaultPath(process.env.CLAWVAULT_PATH);\n }\n\n // Walk up from cwd\n let dir = process.cwd();\n const root = path.parse(dir).root;\n \n while (dir !== root) {\n const validated = validateVaultPath(dir);\n if (validated) return validated;\n \n // Also check memory/ subdirectory (OpenClaw convention)\n const memoryDir = path.join(dir, 'memory');\n const memoryValidated = validateVaultPath(memoryDir);\n if (memoryValidated) return memoryValidated;\n \n dir = path.dirname(dir);\n }\n \n return null;\n}\n\n// Run clawvault command safely (no shell)\nfunction runClawvault(args) {\n try {\n // Use execFileSync to avoid shell injection\n // Arguments are passed as array, not interpolated into shell\n const output = execFileSync('clawvault', args, {\n encoding: 'utf-8',\n timeout: 15000,\n stdio: ['pipe', 'pipe', 'pipe'],\n // Explicitly no shell\n shell: false\n });\n return { success: true, output: output.trim(), code: 0 };\n } catch (err) {\n return { \n success: false, \n output: err.stderr?.toString() || err.message || String(err),\n code: err.status || 1\n };\n }\n}\n\n// Parse recovery output safely\nfunction parseRecoveryOutput(output) {\n if (!output || typeof output !== 'string') {\n return { hadDeath: false, workingOn: null };\n }\n \n const hadDeath = output.includes('Context death detected') || \n output.includes('died') || \n output.includes('\u26a0\ufe0f');\n \n let workingOn = null;\n if (hadDeath) {\n const lines = output.split('\\n');\n const workingOnLine = lines.find(l => l.toLowerCase().includes('working on'));\n if (workingOnLine) {\n const parts = workingOnLine.split(':');\n if (parts.length > 1) {\n workingOn = sanitizeForDisplay(parts.slice(1).join(':').trim());\n }\n }\n }\n \n return { hadDeath, workingOn };\n}\n\n// Handle gateway startup - check for context death\nasync function handleStartup(event) {\n const vaultPath = findVaultPath();\n if (!vaultPath) {\n console.log('[clawvault] No vault found, skipping recovery check');\n return;\n }\n\n console.log(`[clawvault] Checking for context death`);\n\n // Pass vault path as separate argument (not interpolated)\n const result = runClawvault(['recover', '--clear', '-v', vaultPath]);\n \n if (!result.success) {\n console.warn('[clawvault] Recovery check failed');\n return;\n }\n\n const { hadDeath, workingOn } = parseRecoveryOutput(result.output);\n \n if (hadDeath) {\n // Build safe alert message with sanitized content\n const alertParts = ['[ClawVault] Context death detected.'];\n if (workingOn) {\n alertParts.push(`Last working on: ${workingOn}`);\n }\n alertParts.push('Run `clawvault wake` for full recovery context.');\n \n const alertMsg = alertParts.join(' ');\n\n // Inject into event messages if available\n if (event.messages && Array.isArray(event.messages)) {\n event.messages.push(alertMsg);\n }\n \n console.warn('[clawvault] Context death detected, alert injected');\n } else {\n console.log('[clawvault] Clean startup - no context death');\n }\n}\n\n// Handle /new command - auto-checkpoint before reset\nasync function handleNew(event) {\n const vaultPath = findVaultPath();\n if (!vaultPath) {\n console.log('[clawvault] No vault found, skipping auto-checkpoint');\n return;\n }\n\n // Sanitize session info for checkpoint\n const sessionKey = typeof event.sessionKey === 'string' \n ? event.sessionKey.replace(/[^a-zA-Z0-9:_-]/g, '').slice(0, 100)\n : 'unknown';\n const source = typeof event.context?.commandSource === 'string'\n ? event.context.commandSource.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 50)\n : 'cli';\n\n console.log('[clawvault] Auto-checkpoint before /new');\n\n // Pass each argument separately (no shell interpolation)\n const result = runClawvault([\n 'checkpoint',\n '--working-on', `Session reset via /new from ${source}`,\n '--focus', `Pre-reset checkpoint, session: ${sessionKey}`,\n '-v', vaultPath\n ]);\n\n if (result.success) {\n console.log('[clawvault] Auto-checkpoint created');\n } else {\n console.warn('[clawvault] Auto-checkpoint failed');\n }\n}\n\n// Main handler - route events\nconst handler = async (event) => {\n try {\n if (event.type === 'gateway' && event.action === 'startup') {\n await handleStartup(event);\n return;\n }\n\n if (event.type === 'command' && event.action === 'new') {\n await handleNew(event);\n return;\n }\n } catch (err) {\n console.error('[clawvault] Hook error:', err.message || 'unknown error');\n }\n};\n\nexport default handler;\n",617 "inputSchema": {},618 "outputSchema": null,619 "icons": null,620 "annotations": null,621 "meta": null,622 "execution": null623 },624 {625 "name": "index.d.ts",626 "title": null,627 "description": "Script: index.d.ts. Code:\nimport { V as VaultConfig, S as StoreOptions, D as Document, a as SearchOptions, b as SearchResult, c as SyncOptions, d as SyncResult, C as Category, M as MemoryType, H as HandoffDocument, e as SessionRecap } from './types-DO8rJ490.js';\nexport { f as DEFAULT_CATEGORIES, g as DEFAULT_CONFIG, h as MEMORY_TYPES, T as TYPE_TO_CATEGORY, i as VaultMeta } from './types-DO8rJ490.js';\nexport { setupCommand } from './commands/setup.js';\nexport { TemplateVariables, buildTemplateVariables, renderTemplate } from './lib/template-engine.js';\n\n/**\n * ClawVault - The elephant's memory\n */\n\ndeclare class ClawVault {\n private config;\n private search;\n private initialized;\n constructor(vaultPath: string);\n /**\n * Initialize a new vault\n */\n init(options?: Partial<VaultConfig>): Promise<void>;\n /**\n * Load an existing vault\n */\n load(): Promise<void>;\n /**\n * Reindex all documents\n */\n reindex(): Promise<number>;\n /**\n * Load a document from disk\n */\n private loadDocument;\n /**\n * Store a new document\n */\n store(options: StoreOptions): Promise<Document>;\n /**\n * Quick store to inbox\n */\n capture(note: string, title?: string): Promise<Document>;\n /**\n * Search the vault (BM25 via qmd)\n */\n find(query: string, options?: SearchOptions): Promise<SearchResult[]>;\n /**\n * Semantic/vector search (via qmd vsearch)\n */\n vsearch(query: string, options?: SearchOptions): Promise<SearchResult[]>;\n /**\n * Combined search with query expansion (via qmd query)\n */\n query(query: string, options?: SearchOptions): Promise<SearchResult[]>;\n /**\n * Get a document by ID or path\n */\n get(idOrPath: string): Promise<Document | null>;\n /**\n * List documents in a category\n */\n list(category?: string): Promise<Document[]>;\n /**\n * Sync vault to another location (for Obsidian on Windows, etc.)\n */\n sync(options: SyncOptions): Promise<SyncResult>;\n /**\n * Get vault statistics\n */\n stats(): Promise<{\n documents: number;\n categories: {\n [key: string]: number;\n };\n links: number;\n tags: string[];\n }>;\n /**\n * Get all categories\n */\n getCategories(): Category[];\n /**\n * Check if vault is initialized\n */\n isInitialized(): boolean;\n /**\n * Get vault path\n */\n getPath(): string;\n /**\n * Get vault name\n */\n getName(): string;\n /**\n * Get qmd collection name\n */\n getQmdCollection(): string;\n /**\n * Get qmd collection root\n */\n getQmdRoot(): string;\n /**\n * Store a memory with type classification\n * Automatically routes to correct category based on type\n */\n remember(type: MemoryType, title: string, content: string, frontmatter?: Record<string, unknown>): Promise<Document>;\n /**\n * Create a session handoff document\n * Call this before context death or long pauses\n */\n createHandoff(handoff: Omit<HandoffDocument, 'created'>): Promise<Document>;\n /**\n * Format handoff as readable markdown\n */\n private formatHandoff;\n /**\n * Generate a session recap - who I was\n * Call this on bootstrap to restore context\n */\n generateRecap(options?: {\n handoffLimit?: number;\n brief?: boolean;\n }): Promise<SessionRecap>;\n /**\n * Format recap as readable markdown for injection\n */\n formatRecap(recap: SessionRecap, options?: {\n brief?: boolean;\n }): string;\n /**\n * Parse a handoff document back into structured form\n */\n private parseHandoff;\n private applyQmdConfig;\n private slugify;\n private saveIndex;\n private createTemplates;\n private generateReadme;\n private getCategoryDescription;\n}\n/**\n * Find and open the nearest vault (walks up directory tree)\n */\ndeclare function findVault(startPath?: string): Promise<ClawVault | null>;\n/**\n * Create a new vault\n */\ndeclare function createVault(vaultPath: string, options?: Partial<VaultConfig>): Promise<ClawVault>;\n\n/**\n * ClawVault Search Engine - qmd Backend\n * Uses qmd CLI for BM25 and vector search\n */\n\ndeclare const QMD_INSTALL_URL = \"https://github.com/tobi/qmd\";\ndeclare const QMD_INSTALL_COMMAND = \"bun install -g github:tobi/qmd\";\ndeclare class QmdUnavailableError extends Error {\n constructor(message?: string);\n}\n/**\n * Check if qmd is available\n */\ndeclare function hasQmd(): boolean;\n/**\n * Trigger qmd update (reindex)\n */\ndeclare function qmdUpdate(collection?: string): void;\n/**\n * Trigger qmd embed (create/update vector embeddings)\n */\ndeclare function qmdEmbed(collection?: string): void;\n/**\n * QMD Search Engine - wraps qmd CLI\n */\ndeclare class SearchEngine {\n private documents;\n private collection;\n private vaultPath;\n private collectionRoot;\n /**\n * Set the collection name (usually vault name)\n */\n setCollection(name: string): void;\n /**\n * Set the vault path for file resolution\n */\n setVaultPath(vaultPath: string): void;\n /**\n * Set the collection root for qmd:// URI resolution\n */\n setCollectionRoot(root: string): void;\n /**\n * Add or update a document in the local cache\n * Note: qmd indexing happens via qmd update command\n */\n addDocument(doc: Document): void;\n /**\n * Remove a document from the local cache\n */\n removeDocument(id: string): void;\n /**\n * No-op for qmd - indexing is managed externally\n */\n rebuildIDF(): void;\n /**\n * BM25 search via qmd\n */\n search(query: string, options?: SearchOptions): SearchResult[];\n /**\n * Vector/semantic search via qmd vsearch\n */\n vsearch(query: string, options?: SearchOptions): SearchResult[];\n /**\n * Combined search with query expansion (qmd query command)\n */\n query(query: string, options?: SearchOptions): SearchResult[];\n private runQmdQuery;\n /**\n * Convert qmd results to ClawVault SearchResult format\n */\n private convertResults;\n /**\n * Convert qmd:// URI to file path\n */\n private qmdUriToPath;\n /**\n * Clean up qmd snippet format\n */\n private cleanSnippet;\n /**\n * Get all cached documents\n */\n getAllDocuments(): Document[];\n /**\n * Get document count\n */\n get size(): number;\n /**\n * Clear the local document cache\n */\n clear(): void;\n /**\n * Export documents for persistence\n */\n export(): {\n documents: Document[];\n };\n /**\n * Import from persisted data\n */\n import(data: {\n documents: Document[];\n }): void;\n}\n/**\n * Find wiki-links in content\n */\ndeclare function extractWikiLinks(content: string): string[];\n/**\n * Find tags in content (#tag format)\n */\ndeclare function extractTags(content: string): string[];\n\n/**\n * ClawVault \ud83d\udc18 \u2014 An Elephant Never Forgets\n *\n * Structured memory system for AI agents with Obsidian-compatible markdown\n * and embedded semantic search.\n *\n * @example\n * ```typescript\n * import { ClawVault, createVault, findVault } from 'clawvault';\n *\n * // Create a new vault\n * const vault = await createVault('./my-memory');\n *\n * // Store a memory\n * await vault.store({\n * category: 'decisions',\n * title: 'Use ClawVault',\n * content: 'Decided to use ClawVault for memory management.'\n * });\n *\n * // Search memories\n * const results = await vault.find('memory management');\n * console.log(results);\n * ```\n */\n\ndeclare const VERSION: string;\n\nexport { Category, ClawVault, Document, HandoffDocument, MemoryType, QMD_INSTALL_COMMAND, QMD_INSTALL_URL, QmdUnavailableError, SearchEngine, SearchOptions, SearchResult, SessionRecap, StoreOptions, SyncOptions, SyncResult, VERSION, VaultConfig, createVault, extractTags, extractWikiLinks, findVault, hasQmd, qmdEmbed, qmdUpdate };\n",628 "inputSchema": {},629 "outputSchema": null,630 "icons": null,631 "annotations": null,632 "meta": null,633 "execution": null634 },635 {636 "name": "chunk-L53L5FCL.js",637 "title": null,638 "description": "Script: chunk-L53L5FCL.js. Code:\n// src/lib/session-repair.ts\nimport * as fs from \"fs\";\nfunction parseTranscript(filePath) {\n const content = fs.readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((line) => line.trim());\n const entries = [];\n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i];\n try {\n const entry = JSON.parse(raw);\n entries.push({ line: i + 1, entry, raw });\n } catch {\n console.warn(`Warning: Could not parse line ${i + 1}`);\n }\n }\n return entries;\n}\nfunction extractToolUses(entries) {\n const toolUses = /* @__PURE__ */ new Map();\n for (const { line, entry } of entries) {\n if (entry.type !== \"message\") continue;\n if (entry.message?.role !== \"assistant\") continue;\n const isAborted = entry.message.stopReason === \"aborted\";\n const content = entry.message.content || [];\n for (const block of content) {\n if (block.type === \"toolCall\" || block.type === \"tool_use\" || block.type === \"functionCall\") {\n if (block.id) {\n const isPartial = !!block.partialJson;\n toolUses.set(block.id, {\n id: block.id,\n lineNumber: line,\n entryId: entry.id,\n isAborted: isAborted || isPartial,\n isPartial,\n name: block.name\n });\n }\n }\n }\n }\n return toolUses;\n}\nfunction findCorruptedEntries(entries, toolUses) {\n const corrupted = [];\n const entriesToRemove = /* @__PURE__ */ new Set();\n for (const [toolId, info] of toolUses) {\n if (info.isAborted) {\n corrupted.push({\n lineNumber: info.lineNumber,\n entryId: info.entryId,\n type: \"aborted_tool_use\",\n toolUseId: toolId,\n description: `Aborted tool_use${info.name ? ` (${info.name})` : \"\"} with id: ${toolId}`\n });\n entriesToRemove.add(info.entryId);\n }\n }\n for (const { line, entry } of entries) {\n if (entry.type !== \"message\") continue;\n if (entry.message?.role !== \"toolResult\") continue;\n const content = entry.message.content || [];\n let toolCallId;\n const msg = entry.message;\n toolCallId = msg.toolCallId || msg.toolUseId;\n if (!toolCallId) {\n for (const block of content) {\n if (block.toolCallId || block.toolUseId) {\n toolCallId = block.toolCallId || block.toolUseId;\n break;\n }\n }\n }\n if (!toolCallId) continue;\n const toolUse = toolUses.get(toolCallId);\n if (!toolUse || toolUse.isAborted) {\n corrupted.push({\n lineNumber: line,\n entryId: entry.id,\n type: \"orphaned_tool_result\",\n toolUseId: toolCallId,\n description: toolUse ? `Orphaned tool_result references aborted tool_use: ${toolCallId}` : `Orphaned tool_result references non-existent tool_use: ${toolCallId}`\n });\n entriesToRemove.add(entry.id);\n }\n }\n return { corrupted, entriesToRemove };\n}\nfunction computeParentRelinks(entries, entriesToRemove) {\n const relinks = [];\n const entryParents = /* @__PURE__ */ new Map();\n for (const { entry } of entries) {\n entryParents.set(entry.id, entry.parentId);\n }\n for (const { line, entry } of entries) {\n if (entriesToRemove.has(entry.id)) continue;\n if (!entry.parentId) continue;\n if (!entriesToRemove.has(entry.parentId)) continue;\n let newParentId = entry.parentId;\n while (newParentId && entriesToRemove.has(newParentId)) {\n newParentId = entryParents.get(newParentId) || null;\n }\n if (newParentId !== entry.parentId) {\n relinks.push({\n lineNumber: line,\n entryId: entry.id,\n oldParentId: entry.parentId,\n newParentId: newParentId || \"null\"\n });\n }\n }\n return relinks;\n}\nfunction analyzeSession(filePath) {\n const entries = parseTranscript(filePath);\n const sessionEntry = entries.find((e) => e.entry.type === \"session\");\n const sessionId = sessionEntry?.entry.id || \"unknown\";\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const parentRelinks = computeParentRelinks(entries, entriesToRemove);\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n repaired: false\n };\n}\nfunction repairSession(filePath, options = {}) {\n const { backup = true, dryRun = false } = options;\n const entries = parseTranscript(filePath);\n const sessionEntry = entries.find((e) => e.entry.type === \"session\");\n const sessionId = sessionEntry?.entry.id || \"unknown\";\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const parentRelinks = computeParentRelinks(entries, entriesToRemove);\n if (corrupted.length === 0) {\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: [],\n parentRelinks: [],\n removedCount: 0,\n relinkedCount: 0,\n repaired: false\n };\n }\n if (dryRun) {\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n repaired: false\n };\n }\n let backupPath;\n if (backup) {\n const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, \"\").replace(\"T\", \"-\").slice(0, 15);\n backupPath = `${filePath}.backup-${timestamp}`;\n fs.copyFileSync(filePath, backupPath);\n }\n const relinkMap = /* @__PURE__ */ new Map();\n for (const relink of parentRelinks) {\n relinkMap.set(relink.entryId, relink.newParentId === \"null\" ? null : relink.newParentId);\n }\n const repairedLines = [];\n for (const { entry, raw } of entries) {\n if (entriesToRemove.has(entry.id)) continue;\n if (relinkMap.has(entry.id)) {\n const newEntry = { ...entry, parentId: relinkMap.get(entry.id) };\n repairedLines.push(JSON.stringify(newEntry));\n } else {\n repairedLines.push(raw);\n }\n }\n fs.writeFileSync(filePath, repairedLines.join(\"\\n\") + \"\\n\");\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n backupPath,\n repaired: true\n };\n}\n\nexport {\n parseTranscript,\n extractToolUses,\n findCorruptedEntries,\n computeParentRelinks,\n analyzeSession,\n repairSession\n};\n",639 "inputSchema": {},640 "outputSchema": null,641 "icons": null,642 "annotations": null,643 "meta": null,644 "execution": null645 },646 {647 "name": "chunk-7ZRP733D.js",648 "title": null,649 "description": "Script: chunk-7ZRP733D.js. Code:\n// src/lib/time.ts\nfunction formatAge(ms) {\n if (!Number.isFinite(ms)) return \"unknown\";\n const seconds = Math.max(0, Math.floor(ms / 1e3));\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n if (days > 0) return `${days}d ${hours % 24}h`;\n if (hours > 0) return `${hours}h ${minutes % 60}m`;\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\n}\n\nexport {\n formatAge\n};\n",650 "inputSchema": {},651 "outputSchema": null,652 "icons": null,653 "annotations": null,654 "meta": null,655 "execution": null656 },657 {658 "name": "template-engine.js",659 "title": null,660 "description": "Script: template-engine.js. Code:\nimport {\n buildTemplateVariables,\n renderTemplate\n} from \"../chunk-7766SIJP.js\";\nexport {\n buildTemplateVariables,\n renderTemplate\n};\n",661 "inputSchema": {},662 "outputSchema": null,663 "icons": null,664 "annotations": null,665 "meta": null,666 "execution": null667 },668 {669 "name": "entity-index.js",670 "title": null,671 "description": "Script: entity-index.js. Code:\nimport {\n buildEntityIndex,\n getSortedAliases\n} from \"../chunk-J7ZWCI2C.js\";\nexport {\n buildEntityIndex,\n getSortedAliases\n};\n",672 "inputSchema": {},673 "outputSchema": null,674 "icons": null,675 "annotations": null,676 "meta": null,677 "execution": null678 },679 {680 "name": "session-repair.d.ts",681 "title": null,682 "description": "Script: session-repair.d.ts. Code:\n/**\n * Session transcript repair logic\n *\n * Repairs corrupted OpenClaw session transcripts by:\n * 1. Finding aborted tool_use blocks (stopReason: \"aborted\", partialJson present)\n * 2. Finding orphaned tool_result messages that reference non-existent tool_use IDs\n * 3. Removing both the aborted entries and orphaned results\n * 4. Relinking parent chain references\n */\ninterface TranscriptEntry {\n type: 'session' | 'message' | 'compaction' | 'custom' | 'thinking_level_change' | string;\n id: string;\n parentId: string | null;\n timestamp: string;\n message?: {\n role: 'user' | 'assistant' | 'toolResult' | 'system';\n content: Array<{\n type: string;\n id?: string;\n name?: string;\n arguments?: unknown;\n toolCallId?: string;\n toolUseId?: string;\n partialJson?: string;\n text?: string;\n }>;\n stopReason?: string;\n errorMessage?: string;\n };\n summary?: string;\n customType?: string;\n data?: unknown;\n thinkingLevel?: string;\n}\ninterface ToolUseInfo {\n id: string;\n lineNumber: number;\n entryId: string;\n isAborted: boolean;\n isPartial: boolean;\n name?: string;\n}\ninterface CorruptedEntry {\n lineNumber: number;\n entryId: string;\n type: 'aborted_tool_use' | 'orphaned_tool_result';\n toolUseId: string;\n description: string;\n}\ninterface ParentRelink {\n lineNumber: number;\n entryId: string;\n oldParentId: string;\n newParentId: string;\n}\ninterface RepairResult {\n sessionId: string;\n totalLines: number;\n corruptedEntries: CorruptedEntry[];\n parentRelinks: ParentRelink[];\n removedCount: number;\n relinkedCount: number;\n backupPath?: string;\n repaired: boolean;\n}\n/**\n * Parse a JSONL file into transcript entries with line numbers\n */\ndeclare function parseTranscript(filePath: string): Array<{\n line: number;\n entry: TranscriptEntry;\n raw: string;\n}>;\n/**\n * Extract all tool_use IDs from assistant messages\n */\ndeclare function extractToolUses(entries: Array<{\n line: number;\n entry: TranscriptEntry;\n}>): Map<string, ToolUseInfo>;\n/**\n * Find orphaned tool_result messages that reference non-existent or aborted tool_use IDs\n */\ndeclare function findCorruptedEntries(entries: Array<{\n line: number;\n entry: TranscriptEntry;\n}>, toolUses: Map<string, ToolUseInfo>): {\n corrupted: CorruptedEntry[];\n entriesToRemove: Set<string>;\n};\n/**\n * Compute parent chain relinks after removing entries\n */\ndeclare function computeParentRelinks(entries: Array<{\n line: number;\n entry: TranscriptEntry;\n}>, entriesToRemove: Set<string>): ParentRelink[];\n/**\n * Analyze a session transcript for corruption without modifying it\n */\ndeclare function analyzeSession(filePath: string): RepairResult;\n/**\n * Repair a session transcript\n */\ndeclare function repairSession(filePath: string, options?: {\n backup?: boolean;\n dryRun?: boolean;\n}): RepairResult;\n\nexport { type CorruptedEntry, type ParentRelink, type RepairResult, type ToolUseInfo, type TranscriptEntry, analyzeSession, computeParentRelinks, extractToolUses, findCorruptedEntries, parseTranscript, repairSession };\n",683 "inputSchema": {},684 "outputSchema": null,685 "icons": null,686 "annotations": null,687 "meta": null,688 "execution": null689 },690 {691 "name": "entity-index.d.ts",692 "title": null,693 "description": "Script: entity-index.d.ts. Code:\ninterface EntityEntry {\n path: string;\n aliases: string[];\n}\ninterface EntityIndex {\n entries: Map<string, string>;\n byPath: Map<string, EntityEntry>;\n}\n/**\n * Build an entity index from all markdown files in the vault.\n * Extracts linkable names from:\n * - Filename (without .md)\n * - Frontmatter `title` field\n * - Frontmatter `aliases` array\n */\ndeclare function buildEntityIndex(vaultPath: string): EntityIndex;\n/**\n * Get all entities sorted by alias length (longest first)\n * This ensures \"Justin Dukes\" is matched before \"Justin\"\n */\ndeclare function getSortedAliases(index: EntityIndex): Array<{\n alias: string;\n path: string;\n}>;\n\nexport { type EntityEntry, type EntityIndex, buildEntityIndex, getSortedAliases };\n",694 "inputSchema": {},695 "outputSchema": null,696 "icons": null,697 "annotations": null,698 "meta": null,699 "execution": null700 },701 {702 "name": "session-utils.js",703 "title": null,704 "description": "Script: session-utils.js. Code:\nimport {\n backupSession,\n findMainSession,\n findSessionById,\n getOpenClawAgentsDir,\n getSessionFilePath,\n getSessionsDir,\n getSessionsJsonPath,\n listAgents,\n listSessions,\n loadSessionsStore\n} from \"../chunk-AZRV2I5U.js\";\nexport {\n backupSession,\n findMainSession,\n findSessionById,\n getOpenClawAgentsDir,\n getSessionFilePath,\n getSessionsDir,\n getSessionsJsonPath,\n listAgents,\n listSessions,\n loadSessionsStore\n};\n",705 "inputSchema": {},706 "outputSchema": null,707 "icons": null,708 "annotations": null,709 "meta": null,710 "execution": null711 },712 {713 "name": "template-engine.d.ts",714 "title": null,715 "description": "Script: template-engine.d.ts. Code:\ninterface TemplateVariables {\n title: string;\n date: string;\n datetime: string;\n type: string;\n}\ndeclare function buildTemplateVariables(input?: Partial<TemplateVariables>, now?: Date): TemplateVariables;\ndeclare function renderTemplate(template: string, variables: TemplateVariables): string;\n\nexport { type TemplateVariables, buildTemplateVariables, renderTemplate };\n",716 "inputSchema": {},717 "outputSchema": null,718 "icons": null,719 "annotations": null,720 "meta": null,721 "execution": null722 },723 {724 "name": "session-repair.js",725 "title": null,726 "description": "Script: session-repair.js. Code:\nimport {\n analyzeSession,\n computeParentRelinks,\n extractToolUses,\n findCorruptedEntries,\n parseTranscript,\n repairSession\n} from \"../chunk-L53L5FCL.js\";\nexport {\n analyzeSession,\n computeParentRelinks,\n extractToolUses,\n findCorruptedEntries,\n parseTranscript,\n repairSession\n};\n",727 "inputSchema": {},728 "outputSchema": null,729 "icons": null,730 "annotations": null,731 "meta": null,732 "execution": null733 },734 {735 "name": "config.js",736 "title": null,737 "description": "Script: config.js. Code:\nimport {\n getVaultPath\n} from \"../chunk-4KDZZW4X.js\";\nexport {\n getVaultPath\n};\n",738 "inputSchema": {},739 "outputSchema": null,740 "icons": null,741 "annotations": null,742 "meta": null,743 "execution": null744 },745 {746 "name": "config.d.ts",747 "title": null,748 "description": "Script: config.d.ts. Code:\n/**\n * Get the vault path from CLAWVAULT_PATH env var or throw\n */\ndeclare function getVaultPath(): string;\n\nexport { getVaultPath };\n",749 "inputSchema": {},750 "outputSchema": null,751 "icons": null,752 "annotations": null,753 "meta": null,754 "execution": null755 },756 {757 "name": "auto-linker.d.ts",758 "title": null,759 "description": "Script: auto-linker.d.ts. Code:\nimport { EntityIndex } from './entity-index.js';\n\n/**\n * Auto-link entities in markdown content.\n * Only links first occurrence of each entity.\n * Skips protected ranges (frontmatter, code, existing links, URLs).\n */\ndeclare function autoLink(content: string, index: EntityIndex): string;\n/**\n * Show what would be linked (dry run)\n */\ndeclare function dryRunLink(content: string, index: EntityIndex): Array<{\n alias: string;\n path: string;\n line: number;\n}>;\n/**\n * Find unlinked mentions of entities (suggested links).\n */\ndeclare function findUnlinkedMentions(content: string, index: EntityIndex): Array<{\n alias: string;\n path: string;\n line: number;\n}>;\n\nexport { autoLink, dryRunLink, findUnlinkedMentions };\n",760 "inputSchema": {},761 "outputSchema": null,762 "icons": null,763 "annotations": null,764 "meta": null,765 "execution": null766 },767 {768 "name": "session-utils.d.ts",769 "title": null,770 "description": "Script: session-utils.d.ts. Code:\n/**\n * Session discovery utilities for OpenClaw transcripts\n */\ninterface SessionInfo {\n sessionId: string;\n sessionKey: string;\n agentId: string;\n filePath: string;\n updatedAt?: number;\n}\ninterface SessionsStore {\n [sessionKey: string]: {\n sessionId: string;\n updatedAt?: number;\n [key: string]: unknown;\n };\n}\n/**\n * Get the OpenClaw agents directory\n */\ndeclare function getOpenClawAgentsDir(): string;\n/**\n * Get the sessions directory for an agent\n */\ndeclare function getSessionsDir(agentId: string): string;\n/**\n * Get the path to sessions.json for an agent\n */\ndeclare function getSessionsJsonPath(agentId: string): string;\n/**\n * Get the path to a session JSONL file\n */\ndeclare function getSessionFilePath(agentId: string, sessionId: string): string;\n/**\n * List all available agents\n */\ndeclare function listAgents(): string[];\n/**\n * Load sessions.json for an agent\n */\ndeclare function loadSessionsStore(agentId: string): SessionsStore | null;\n/**\n * Find the current/main session for an agent\n */\ndeclare function findMainSession(agentId: string): SessionInfo | null;\n/**\n * Find a session by ID\n */\ndeclare function findSessionById(agentId: string, sessionId: string): SessionInfo | null;\n/**\n * List all sessions for an agent\n */\ndeclare function listSessions(agentId: string): SessionInfo[];\n/**\n * Create a backup of a session file\n */\ndeclare function backupSession(filePath: string): string;\n\nexport { type SessionInfo, type SessionsStore, backupSession, findMainSession, findSessionById, getOpenClawAgentsDir, getSessionFilePath, getSessionsDir, getSessionsJsonPath, listAgents, listSessions, loadSessionsStore };\n",771 "inputSchema": {},772 "outputSchema": null,773 "icons": null,774 "annotations": null,775 "meta": null,776 "execution": null777 },778 {779 "name": "auto-linker.js",780 "title": null,781 "description": "Script: auto-linker.js. Code:\nimport {\n autoLink,\n dryRunLink,\n findUnlinkedMentions\n} from \"../chunk-42MXU7A6.js\";\nimport \"../chunk-J7ZWCI2C.js\";\nexport {\n autoLink,\n dryRunLink,\n findUnlinkedMentions\n};\n",782 "inputSchema": {},783 "outputSchema": null,784 "icons": null,785 "annotations": null,786 "meta": null,787 "execution": null788 },789 {790 "name": "chunk-7766SIJP.js",791 "title": null,792 "description": "Script: chunk-7766SIJP.js. Code:\n// src/lib/template-engine.ts\nfunction buildTemplateVariables(input = {}, now = /* @__PURE__ */ new Date()) {\n const datetime = input.datetime ?? now.toISOString();\n const date = input.date ?? datetime.split(\"T\")[0];\n return {\n title: input.title ?? \"\",\n type: input.type ?? \"\",\n date,\n datetime\n };\n}\nfunction renderTemplate(template, variables) {\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_-]+)\\s*\\}\\}/g, (match, key) => {\n const value = variables[key];\n return value !== void 0 ? String(value) : match;\n });\n}\n\nexport {\n buildTemplateVariables,\n renderTemplate\n};\n",793 "inputSchema": {},794 "outputSchema": null,795 "icons": null,796 "annotations": null,797 "meta": null,798 "execution": null799 },800 {801 "name": "chunk-MXNXWOPL.js",802 "title": null,803 "description": "Script: chunk-MXNXWOPL.js. Code:\nimport {\n DEFAULT_CATEGORIES,\n QmdUnavailableError,\n SearchEngine,\n TYPE_TO_CATEGORY,\n extractTags,\n extractWikiLinks,\n hasQmd,\n qmdEmbed,\n qmdUpdate\n} from \"./chunk-VJIFT5T5.js\";\n\n// src/lib/vault.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport matter from \"gray-matter\";\nimport { glob } from \"glob\";\nvar CONFIG_FILE = \".clawvault.json\";\nvar INDEX_FILE = \".clawvault-index.json\";\nvar ClawVault = class {\n config;\n search;\n initialized = false;\n constructor(vaultPath) {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n this.config = {\n path: path.resolve(vaultPath),\n name: path.basename(vaultPath),\n categories: DEFAULT_CATEGORIES,\n qmdCollection: void 0,\n qmdRoot: void 0\n };\n this.search = new SearchEngine();\n this.applyQmdConfig();\n }\n /**\n * Initialize a new vault\n */\n async init(options = {}) {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vaultPath = this.config.path;\n this.config = { ...this.config, ...options };\n this.applyQmdConfig();\n if (!fs.existsSync(vaultPath)) {\n fs.mkdirSync(vaultPath, { recursive: true });\n }\n for (const category of this.config.categories) {\n const catPath = path.join(vaultPath, category);\n if (!fs.existsSync(catPath)) {\n fs.mkdirSync(catPath, { recursive: true });\n }\n }\n await this.createTemplates();\n const readmePath = path.join(vaultPath, \"README.md\");\n if (!fs.existsSync(readmePath)) {\n fs.writeFileSync(readmePath, this.generateReadme());\n }\n const configPath = path.join(vaultPath, CONFIG_FILE);\n const meta = {\n name: this.config.name,\n version: \"1.0.0\",\n created: (/* @__PURE__ */ new Date()).toISOString(),\n lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),\n categories: this.config.categories,\n documentCount: 0,\n qmdCollection: this.getQmdCollection(),\n qmdRoot: this.getQmdRoot()\n };\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n this.initialized = true;\n }\n /**\n * Load an existing vault\n */\n async load() {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vaultPath = this.config.path;\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (!fs.existsSync(configPath)) {\n throw new Error(`Not a ClawVault: ${vaultPath} (missing ${CONFIG_FILE})`);\n }\n const meta = JSON.parse(fs.readFileSync(configPath, \"utf-8\"));\n this.config.name = meta.name;\n this.config.categories = meta.categories;\n this.config.qmdCollection = meta.qmdCollection;\n this.config.qmdRoot = meta.qmdRoot;\n if (!meta.qmdCollection || !meta.qmdRoot) {\n meta.qmdCollection = meta.qmdCollection || meta.name;\n meta.qmdRoot = meta.qmdRoot || this.config.path;\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n }\n this.applyQmdConfig(meta);\n await this.reindex();\n this.initialized = true;\n }\n /**\n * Reindex all documents\n */\n async reindex() {\n this.search.clear();\n const files = await glob(\"**/*.md\", {\n cwd: this.config.path,\n ignore: [\"**/node_modules/**\", \"**/.*\"]\n });\n for (const file of files) {\n const doc = await this.loadDocument(file);\n if (doc) {\n this.search.addDocument(doc);\n }\n }\n await this.saveIndex();\n return this.search.size;\n }\n /**\n * Load a document from disk\n */\n async loadDocument(relativePath) {\n try {\n const fullPath = path.join(this.config.path, relativePath);\n const content = fs.readFileSync(fullPath, \"utf-8\");\n const { data: frontmatter, content: body } = matter(content);\n const stats = fs.statSync(fullPath);\n const parts = relativePath.split(path.sep);\n const category = parts.length > 1 ? parts[0] : \"root\";\n const filename = path.basename(relativePath, \".md\");\n return {\n id: relativePath.replace(/\\.md$/, \"\"),\n path: fullPath,\n category,\n title: frontmatter.title || filename,\n content: body,\n frontmatter,\n links: extractWikiLinks(body),\n tags: extractTags(body),\n modified: stats.mtime\n };\n } catch (err) {\n console.error(`Error loading ${relativePath}:`, err);\n return null;\n }\n }\n /**\n * Store a new document\n */\n async store(options) {\n const {\n category,\n title,\n content,\n frontmatter = {},\n overwrite = false,\n qmdUpdate: triggerUpdate = false,\n qmdEmbed: triggerEmbed = false\n } = options;\n const filename = this.slugify(title) + \".md\";\n const relativePath = path.join(category, filename);\n const fullPath = path.join(this.config.path, relativePath);\n if (fs.existsSync(fullPath) && !overwrite) {\n throw new Error(`Document already exists: ${relativePath}. Use overwrite: true to replace.`);\n }\n const categoryPath = path.join(this.config.path, category);\n if (!fs.existsSync(categoryPath)) {\n fs.mkdirSync(categoryPath, { recursive: true });\n }\n const fm = {\n title,\n date: (/* @__PURE__ */ new Date()).toISOString().split(\"T\")[0],\n ...frontmatter\n };\n const fileContent = matter.stringify(content, fm);\n fs.writeFileSync(fullPath, fileContent);\n const doc = await this.loadDocument(relativePath);\n if (doc) {\n this.search.addDocument(doc);\n await this.saveIndex();\n }\n if (triggerUpdate || triggerEmbed) {\n qmdUpdate(this.getQmdCollection());\n if (triggerEmbed) {\n qmdEmbed(this.getQmdCollection());\n }\n }\n return doc;\n }\n /**\n * Quick store to inbox\n */\n async capture(note, title) {\n const autoTitle = title || `note-${Date.now()}`;\n return this.store({\n category: \"inbox\",\n title: autoTitle,\n content: note\n });\n }\n /**\n * Search the vault (BM25 via qmd)\n */\n async find(query, options = {}) {\n return this.search.search(query, options);\n }\n /**\n * Semantic/vector search (via qmd vsearch)\n */\n async vsearch(query, options = {}) {\n return this.search.vsearch(query, options);\n }\n /**\n * Combined search with query expansion (via qmd query)\n */\n async query(query, options = {}) {\n return this.search.query(query, options);\n }\n /**\n * Get a document by ID or path\n */\n async get(idOrPath) {\n const normalized = idOrPath.replace(/\\.md$/, \"\");\n const docs = this.search.getAllDocuments();\n return docs.find((d) => d.id === normalized) || null;\n }\n /**\n * List documents in a category\n */\n async list(category) {\n const docs = this.search.getAllDocuments();\n if (category) {\n return docs.filter((d) => d.category === category);\n }\n return docs;\n }\n /**\n * Sync vault to another location (for Obsidian on Windows, etc.)\n */\n async sync(options) {\n const { target, deleteOrphans = false, dryRun = false } = options;\n const result = {\n copied: [],\n deleted: [],\n unchanged: [],\n errors: []\n };\n const sourceFiles = await glob(\"**/*.md\", {\n cwd: this.config.path,\n ignore: [\"**/node_modules/**\"]\n });\n if (!dryRun && !fs.existsSync(target)) {\n fs.mkdirSync(target, { recursive: true });\n }\n for (const file of sourceFiles) {\n const sourcePath = path.join(this.config.path, file);\n const targetPath = path.join(target, file);\n try {\n const sourceStats = fs.statSync(sourcePath);\n let shouldCopy = true;\n if (fs.existsSync(targetPath)) {\n const targetStats = fs.statSync(targetPath);\n if (sourceStats.mtime <= targetStats.mtime) {\n result.unchanged.push(file);\n shouldCopy = false;\n }\n }\n if (shouldCopy) {\n if (!dryRun) {\n const targetDir = path.dirname(targetPath);\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n fs.copyFileSync(sourcePath, targetPath);\n }\n result.copied.push(file);\n }\n } catch (err) {\n result.errors.push(`${file}: ${err}`);\n }\n }\n if (deleteOrphans) {\n const targetFiles = await glob(\"**/*.md\", { cwd: target });\n const sourceSet = new Set(sourceFiles);\n for (const file of targetFiles) {\n if (!sourceSet.has(file)) {\n if (!dryRun) {\n fs.unlinkSync(path.join(target, file));\n }\n result.deleted.push(file);\n }\n }\n }\n return result;\n }\n /**\n * Get vault statistics\n */\n async stats() {\n const docs = this.search.getAllDocuments();\n const categories = {};\n const allTags = /* @__PURE__ */ new Set();\n let totalLinks = 0;\n for (const doc of docs) {\n categories[doc.category] = (categories[doc.category] || 0) + 1;\n totalLinks += doc.links.length;\n doc.tags.forEach((t) => allTags.add(t));\n }\n return {\n documents: docs.length,\n categories,\n links: totalLinks,\n tags: [...allTags].sort()\n };\n }\n /**\n * Get all categories\n */\n getCategories() {\n return this.config.categories;\n }\n /**\n * Check if vault is initialized\n */\n isInitialized() {\n return this.initialized;\n }\n /**\n * Get vault path\n */\n getPath() {\n return this.config.path;\n }\n /**\n * Get vault name\n */\n getName() {\n return this.config.name;\n }\n /**\n * Get qmd collection name\n */\n getQmdCollection() {\n return this.config.qmdCollection || this.config.name;\n }\n /**\n * Get qmd collection root\n */\n getQmdRoot() {\n return this.config.qmdRoot || this.config.path;\n }\n // === Memory Type System ===\n /**\n * Store a memory with type classification\n * Automatically routes to correct category based on type\n */\n async remember(type, title, content, frontmatter = {}) {\n const category = TYPE_TO_CATEGORY[type];\n return this.store({\n category,\n title,\n content,\n frontmatter: { ...frontmatter, memoryType: type }\n });\n }\n // === Handoff System ===\n /**\n * Create a session handoff document\n * Call this before context death or long pauses\n */\n async createHandoff(handoff) {\n const now = /* @__PURE__ */ new Date();\n const dateStr = now.toISOString().split(\"T\")[0];\n const timeStr = now.toISOString().split(\"T\")[1].slice(0, 5).replace(\":\", \"\");\n const fullHandoff = {\n ...handoff,\n created: now.toISOString()\n };\n const content = this.formatHandoff(fullHandoff);\n const frontmatter = {\n type: \"handoff\",\n workingOn: handoff.workingOn,\n blocked: handoff.blocked,\n nextSteps: handoff.nextSteps\n };\n if (handoff.sessionKey) frontmatter.sessionKey = handoff.sessionKey;\n if (handoff.feeling) frontmatter.feeling = handoff.feeling;\n if (handoff.decisions) frontmatter.decisions = handoff.decisions;\n if (handoff.openQuestions) frontmatter.openQuestions = handoff.openQuestions;\n return this.store({\n category: \"handoffs\",\n title: `handoff-${dateStr}-${timeStr}`,\n content,\n frontmatter\n });\n }\n /**\n * Format handoff as readable markdown\n */\n formatHandoff(h) {\n let md = `# Session Handoff\n\n`;\n md += `**Created:** ${h.created}\n`;\n if (h.sessionKey) md += `**Session:** ${h.sessionKey}\n`;\n if (h.feeling) md += `**Feeling:** ${h.feeling}\n`;\n md += `\n`;\n md += `## Working On\n`;\n h.workingOn.forEach((w) => md += `- ${w}\n`);\n md += `\n`;\n md += `## Blocked\n`;\n if (h.blocked.length === 0) md += `- Nothing currently blocked\n`;\n else h.blocked.forEach((b) => md += `- ${b}\n`);\n md += `\n`;\n md += `## Next Steps\n`;\n h.nextSteps.forEach((n) => md += `- ${n}\n`);\n if (h.decisions && h.decisions.length > 0) {\n md += `\n## Decisions Made\n`;\n h.decisions.forEach((d) => md += `- ${d}\n`);\n }\n if (h.openQuestions && h.openQuestions.length > 0) {\n md += `\n## Open Questions\n`;\n h.openQuestions.forEach((q) => md += `- ${q}\n`);\n }\n return md;\n }\n // === Session Recap (Bootstrap Hook) ===\n /**\n * Generate a session recap - who I was\n * Call this on bootstrap to restore context\n */\n async generateRecap(options = {}) {\n const { handoffLimit = 3, brief = false } = options;\n const handoffDocs = await this.list(\"handoffs\");\n const recentHandoffs = handoffDocs.sort((a, b) => b.modified.getTime() - a.modified.getTime()).slice(0, handoffLimit).map((doc) => this.parseHandoff(doc));\n const projectDocs = await this.list(\"projects\");\n const activeProjects = projectDocs.filter((d) => d.frontmatter.status !== \"completed\" && d.frontmatter.status !== \"archived\").map((d) => d.title);\n const commitmentDocs = await this.list(\"commitments\");\n const pendingCommitments = commitmentDocs.filter((d) => d.frontmatter.status !== \"done\").map((d) => d.title);\n const decisionDocs = await this.list(\"decisions\");\n const recentDecisions = decisionDocs.sort((a, b) => b.modified.getTime() - a.modified.getTime()).slice(0, brief ? 3 : 5).map((d) => d.title);\n const lessonDocs = await this.list(\"lessons\");\n const recentLessons = lessonDocs.sort((a, b) => b.modified.getTime() - a.modified.getTime()).slice(0, brief ? 3 : 5).map((d) => d.title);\n let keyRelationships = [];\n if (!brief) {\n const peopleDocs = await this.list(\"people\");\n keyRelationships = peopleDocs.filter((d) => d.frontmatter.importance === \"high\" || d.frontmatter.role).map((d) => `${d.title}${d.frontmatter.role ? ` (${d.frontmatter.role})` : \"\"}`);\n }\n const feelings = recentHandoffs.map((h) => h.feeling).filter(Boolean);\n const emotionalArc = feelings.length > 0 ? feelings.join(\" \\u2192 \") : void 0;\n return {\n generated: (/* @__PURE__ */ new Date()).toISOString(),\n recentHandoffs,\n activeProjects,\n pendingCommitments,\n recentDecisions,\n recentLessons,\n keyRelationships,\n emotionalArc\n };\n }\n /**\n * Format recap as readable markdown for injection\n */\n formatRecap(recap, options = {}) {\n const { brief = false } = options;\n let md = `# Who I Was\n\n`;\n md += `*Generated: ${recap.generated}*\n\n`;\n if (recap.emotionalArc) {\n md += `**Emotional arc:** ${recap.emotionalArc}\n\n`;\n }\n if (recap.recentHandoffs.length > 0) {\n md += `## Recent Sessions\n`;\n for (const h of recap.recentHandoffs) {\n if (brief) {\n md += `- **${h.created.split(\"T\")[0]}:** ${h.workingOn.slice(0, 2).join(\", \")}`;\n if (h.nextSteps.length > 0) md += ` \\u2192 ${h.nextSteps[0]}`;\n md += `\n`;\n } else {\n md += `\n### ${h.created.split(\"T\")[0]}\n`;\n md += `**Working on:** ${h.workingOn.join(\", \")}\n`;\n if (h.blocked.length > 0) md += `**Blocked:** ${h.blocked.join(\", \")}\n`;\n md += `**Next:** ${h.nextSteps.join(\", \")}\n`;\n }\n }\n md += `\n`;\n }\n if (recap.activeProjects.length > 0) {\n md += `## Active Projects\n`;\n recap.activeProjects.forEach((p) => md += `- ${p}\n`);\n md += `\n`;\n }\n if (recap.pendingCommitments.length > 0) {\n md += `## Pending Commitments\n`;\n recap.pendingCommitments.forEach((c) => md += `- ${c}\n`);\n md += `\n`;\n }\n if (recap.recentDecisions && recap.recentDecisions.length > 0) {\n md += `## Recent Decisions\n`;\n recap.recentDecisions.forEach((d) => md += `- ${d}\n`);\n md += `\n`;\n }\n if (recap.recentLessons.length > 0) {\n md += `## Recent Lessons\n`;\n recap.recentLessons.forEach((l) => md += `- ${l}\n`);\n md += `\n`;\n }\n if (!brief && recap.keyRelationships.length > 0) {\n md += `## Key People\n`;\n recap.keyRelationships.forEach((r) => md += `- ${r}\n`);\n }\n return md;\n }\n /**\n * Parse a handoff document back into structured form\n */\n parseHandoff(doc) {\n return {\n created: doc.frontmatter.date || doc.modified.toISOString(),\n sessionKey: doc.frontmatter.sessionKey,\n workingOn: doc.frontmatter.workingOn || [],\n blocked: doc.frontmatter.blocked || [],\n nextSteps: doc.frontmatter.nextSteps || [],\n decisions: doc.frontmatter.decisions,\n openQuestions: doc.frontmatter.openQuestions,\n feeling: doc.frontmatter.feeling\n };\n }\n // === Private helpers ===\n applyQmdConfig(meta) {\n const collection = meta?.qmdCollection || this.config.qmdCollection || this.config.name;\n const root = meta?.qmdRoot || this.config.qmdRoot || this.config.path;\n this.config.qmdCollection = collection;\n this.config.qmdRoot = root;\n this.search.setVaultPath(this.config.path);\n this.search.setCollection(collection);\n this.search.setCollectionRoot(root);\n }\n slugify(text) {\n return text.toLowerCase().replace(/[^\\w\\s-]/g, \"\").replace(/\\s+/g, \"-\").replace(/-+/g, \"-\").trim();\n }\n async saveIndex() {\n const indexPath = path.join(this.config.path, INDEX_FILE);\n const data = this.search.export();\n fs.writeFileSync(indexPath, JSON.stringify(data, null, 2));\n const configPath = path.join(this.config.path, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n const meta = JSON.parse(fs.readFileSync(configPath, \"utf-8\"));\n meta.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();\n meta.documentCount = this.search.size;\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n }\n }\n async createTemplates() {\n const templatesPath = path.join(this.config.path, \"templates\");\n if (!fs.existsSync(templatesPath)) {\n fs.mkdirSync(templatesPath, { recursive: true });\n }\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(moduleDir, \"../templates\"),\n path.resolve(moduleDir, \"../../templates\")\n ];\n const builtinDir = candidates.find((dir) => fs.existsSync(dir) && fs.statSync(dir).isDirectory());\n if (!builtinDir) return;\n for (const entry of fs.readdirSync(builtinDir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue;\n if (entry.name === \"daily.md\") continue;\n const sourcePath = path.join(builtinDir, entry.name);\n const targetPath = path.join(templatesPath, entry.name);\n if (!fs.existsSync(targetPath)) {\n fs.copyFileSync(sourcePath, targetPath);\n }\n }\n }\n generateReadme() {\n return `# ${this.config.name} \\u{1F418}\n\nAn elephant never forgets.\n\n## Structure\n\n${this.config.categories.map((c) => `- \\`/${c}/\\` \\u2014 ${this.getCategoryDescription(c)}`).join(\"\\n\")}\n\n## Quick Search\n\n\\`\\`\\`bash\nclawvault search \"query\"\n\\`\\`\\`\n\n## Quick Capture\n\n\\`\\`\\`bash\nclawvault store --category inbox --title \"note\" --content \"...\"\n\\`\\`\\`\n\n---\n\n*Managed by [ClawVault](https://github.com/Versatly/clawvault)*\n`;\n }\n getCategoryDescription(category) {\n const descriptions = {\n // Memory type categories (Benthic's taxonomy)\n facts: \"Raw information, data points, things that are true\",\n feelings: \"Emotional states, reactions, energy levels\",\n decisions: \"Choices made with context and reasoning\",\n lessons: \"What I learned, insights, patterns observed\",\n commitments: \"Promises, goals, obligations to fulfill\",\n preferences: \"Likes, dislikes, how I want things\",\n people: \"Relationships, one file per person\",\n projects: \"Active work, ventures, ongoing efforts\",\n // System categories\n handoffs: \"Session bridges \\u2014 what I was doing, what comes next\",\n transcripts: \"Session summaries and logs\",\n goals: \"Long-term and short-term objectives\",\n patterns: \"Recurring behaviors (\\u2192 lessons)\",\n inbox: \"Quick capture \\u2192 process later\",\n templates: \"Templates for each document type\"\n };\n return descriptions[category] || category;\n }\n};\nasync function findVault(startPath = process.cwd()) {\n let current = path.resolve(startPath);\n while (current !== path.dirname(current)) {\n const configPath = path.join(current, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n const vault = new ClawVault(current);\n await vault.load();\n return vault;\n }\n current = path.dirname(current);\n }\n return null;\n}\nasync function createVault(vaultPath, options = {}) {\n const vault = new ClawVault(vaultPath);\n await vault.init(options);\n return vault;\n}\n\nexport {\n ClawVault,\n findVault,\n createVault\n};\n",804 "inputSchema": {},805 "outputSchema": null,806 "icons": null,807 "annotations": null,808 "meta": null,809 "execution": null810 },811 {812 "name": "chunk-QYJI73KF.js",813 "title": null,814 "description": "Script: chunk-QYJI73KF.js. Code:\nimport {\n DEFAULT_CATEGORIES,\n hasQmd\n} from \"./chunk-VJIFT5T5.js\";\n\n// src/commands/setup.ts\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport { execFileSync } from \"child_process\";\nvar CONFIG_FILE = \".clawvault.json\";\nfunction resolveVaultTarget() {\n const envPath = process.env.CLAWVAULT_PATH?.trim();\n const home = os.homedir();\n if (envPath) {\n const vaultPath = path.resolve(envPath);\n return { vaultPath, source: \"CLAWVAULT_PATH\", existed: fs.existsSync(vaultPath) };\n }\n const candidates = [\n { vaultPath: path.join(home, \".openclaw\", \"workspace\", \"memory\"), source: \"OpenClaw default\" },\n { vaultPath: path.resolve(process.cwd(), \"memory\"), source: \"./memory\" },\n { vaultPath: path.join(home, \"memory\"), source: \"~/memory\" }\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(candidate.vaultPath)) {\n return { ...candidate, existed: true };\n }\n }\n const fallback = candidates[0];\n return { ...fallback, existed: false };\n}\nfunction ensureVaultStructure(vaultPath) {\n fs.mkdirSync(vaultPath, { recursive: true });\n for (const category of DEFAULT_CATEGORIES) {\n fs.mkdirSync(path.join(vaultPath, category), { recursive: true });\n }\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (fs.existsSync(configPath)) return false;\n const now = (/* @__PURE__ */ new Date()).toISOString();\n const name = path.basename(vaultPath);\n const meta = {\n name,\n version: \"1.0.0\",\n created: now,\n lastUpdated: now,\n categories: DEFAULT_CATEGORIES,\n documentCount: 0,\n qmdCollection: name,\n qmdRoot: vaultPath\n };\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n return true;\n}\nfunction getQmdConfig(vaultPath) {\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n try {\n const meta = JSON.parse(fs.readFileSync(configPath, \"utf-8\"));\n return {\n collection: meta.qmdCollection || meta.name || path.basename(vaultPath),\n root: meta.qmdRoot || vaultPath\n };\n } catch {\n return { collection: path.basename(vaultPath), root: vaultPath };\n }\n }\n return { collection: path.basename(vaultPath), root: vaultPath };\n}\nasync function setupCommand() {\n const target = resolveVaultTarget();\n if (target.existed && !fs.statSync(target.vaultPath).isDirectory()) {\n throw new Error(`Vault path is not a directory: ${target.vaultPath}`);\n }\n if (!target.existed) fs.mkdirSync(target.vaultPath, { recursive: true });\n console.log(`${target.existed ? \"Found\" : \"Created\"} vault path (${target.source}): ${target.vaultPath}`);\n const initialized = ensureVaultStructure(target.vaultPath);\n console.log(initialized ? \"Initialized vault structure.\" : \"Vault structure already present.\");\n console.log(\"\\nTip: add this to your shell config:\");\n console.log(` export CLAWVAULT_PATH=\"${target.vaultPath}\"`);\n if (hasQmd()) {\n const { collection, root } = getQmdConfig(target.vaultPath);\n try {\n execFileSync(\"qmd\", [\"collection\", \"add\", root, \"--name\", collection, \"--mask\", \"**/*.md\"], {\n stdio: \"ignore\"\n });\n console.log(`qmd collection ready: ${collection}`);\n } catch {\n console.log(\"qmd collection already exists or could not be created.\");\n }\n } else {\n console.log(\"qmd not found; skipping collection setup.\");\n }\n}\n\nexport {\n setupCommand\n};\n",815 "inputSchema": {},816 "outputSchema": null,817 "icons": null,818 "annotations": null,819 "meta": null,820 "execution": null821 },822 {823 "name": "chunk-42MXU7A6.js",824 "title": null,825 "description": "Script: chunk-42MXU7A6.js. Code:\nimport {\n getSortedAliases\n} from \"./chunk-J7ZWCI2C.js\";\n\n// src/lib/auto-linker.ts\nfunction findProtectedRanges(content) {\n const ranges = [];\n const fmMatch = content.match(/^---\\n[\\s\\S]*?\\n---/);\n if (fmMatch) {\n ranges.push({ start: 0, end: fmMatch[0].length });\n }\n const codeBlockRegex = /```[\\s\\S]*?```|~~~[\\s\\S]*?~~~/g;\n let match;\n while ((match = codeBlockRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n const inlineCodeRegex = /`[^`]+`/g;\n while ((match = inlineCodeRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n const wikiLinkRegex = /\\[\\[[^\\]]+\\]\\]/g;\n while ((match = wikiLinkRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n const urlRegex = /https?:\\/\\/[^\\s)>\\]]+/g;\n while ((match = urlRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n return ranges;\n}\nfunction isProtected(pos, ranges) {\n return ranges.some((r) => pos >= r.start && pos < r.end);\n}\nfunction createLineLookup(content) {\n const lines = content.split(\"\\n\");\n let charPos = 0;\n const lineStarts = [];\n for (const line of lines) {\n lineStarts.push(charPos);\n charPos += line.length + 1;\n }\n return (pos) => {\n for (let i = lineStarts.length - 1; i >= 0; i--) {\n if (pos >= lineStarts[i]) return i + 1;\n }\n return 1;\n };\n}\nfunction autoLink(content, index) {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const linkedEntities = /* @__PURE__ */ new Set();\n let result = content;\n let offset = 0;\n for (const { alias, path } of sortedAliases) {\n if (linkedEntities.has(path)) continue;\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, \"gi\");\n let match;\n while ((match = regex.exec(content)) !== null) {\n const originalPos = match.index;\n const adjustedPos = originalPos + offset;\n if (isProtected(originalPos, protectedRanges)) continue;\n const beforeMatch = result.substring(0, adjustedPos);\n const openBrackets = (beforeMatch.match(/\\[\\[/g) || []).length;\n const closeBrackets = (beforeMatch.match(/\\]\\]/g) || []).length;\n if (openBrackets > closeBrackets) continue;\n const originalText = match[0];\n const replacement = originalText.toLowerCase() === path.split(\"/\").pop()?.toLowerCase() ? `[[${path}]]` : `[[${path}|${originalText}]]`;\n result = result.substring(0, adjustedPos) + replacement + result.substring(adjustedPos + originalText.length);\n offset += replacement.length - originalText.length;\n linkedEntities.add(path);\n break;\n }\n }\n return result;\n}\nfunction dryRunLink(content, index) {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const linkedEntities = /* @__PURE__ */ new Set();\n const matches = [];\n const getLineNumber = createLineLookup(content);\n for (const { alias, path } of sortedAliases) {\n if (linkedEntities.has(path)) continue;\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, \"gi\");\n let match;\n while ((match = regex.exec(content)) !== null) {\n if (isProtected(match.index, protectedRanges)) continue;\n matches.push({\n alias: match[0],\n path,\n line: getLineNumber(match.index)\n });\n linkedEntities.add(path);\n break;\n }\n }\n return matches;\n}\nfunction findUnlinkedMentions(content, index) {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const matches = [];\n const seen = /* @__PURE__ */ new Set();\n const getLineNumber = createLineLookup(content);\n for (const { alias, path } of sortedAliases) {\n if (seen.has(path)) continue;\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, \"gi\");\n let match;\n while ((match = regex.exec(content)) !== null) {\n if (isProtected(match.index, protectedRanges)) continue;\n matches.push({\n alias: match[0],\n path,\n line: getLineNumber(match.index)\n });\n seen.add(path);\n break;\n }\n }\n return matches;\n}\n\nexport {\n autoLink,\n dryRunLink,\n findUnlinkedMentions\n};\n",826 "inputSchema": {},827 "outputSchema": null,828 "icons": null,829 "annotations": null,830 "meta": null,831 "execution": null832 },833 {834 "name": "chunk-MZZJLQNQ.js",835 "title": null,836 "description": "Script: chunk-MZZJLQNQ.js. Code:\n// src/commands/checkpoint.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { execFileSync } from \"child_process\";\nvar CLAWVAULT_DIR = \".clawvault\";\nvar CHECKPOINT_FILE = \"last-checkpoint.json\";\nvar SESSION_STATE_FILE = \"session-state.json\";\nvar DIRTY_DEATH_FLAG = \"dirty-death.flag\";\nvar pendingCheckpoint = null;\nvar pendingData = null;\nfunction ensureClawvaultDir(vaultPath) {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\nfunction writeCheckpointToDisk(dir, data) {\n const checkpointPath = path.join(dir, CHECKPOINT_FILE);\n fs.writeFileSync(checkpointPath, JSON.stringify(data, null, 2));\n const flagPath = path.join(dir, DIRTY_DEATH_FLAG);\n fs.writeFileSync(flagPath, data.timestamp);\n}\nfunction parseTokenEstimate(raw) {\n if (!raw) return void 0;\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : void 0;\n}\nfunction loadSessionState(dir) {\n const sessionStatePath = path.join(dir, SESSION_STATE_FILE);\n if (!fs.existsSync(sessionStatePath)) return null;\n try {\n return JSON.parse(fs.readFileSync(sessionStatePath, \"utf-8\"));\n } catch {\n return null;\n }\n}\nfunction getEnvSessionState() {\n return {\n sessionKey: process.env.OPENCLAW_SESSION_KEY,\n model: process.env.OPENCLAW_MODEL,\n tokenEstimate: parseTokenEstimate(\n process.env.OPENCLAW_TOKEN_ESTIMATE || process.env.OPENCLAW_CONTEXT_TOKENS\n )\n };\n}\nfunction triggerUrgentWake(data) {\n const summary = [\n data.workingOn ? `Working on: ${data.workingOn}` : null,\n data.focus ? `Focus: ${data.focus}` : null,\n data.blocked ? `Blocked: ${data.blocked}` : null\n ].filter(Boolean).join(\" | \");\n const text = summary ? `Urgent checkpoint saved. ${summary}` : \"Urgent checkpoint saved.\";\n try {\n execFileSync(\"openclaw\", [\"gateway\", \"wake\", \"--text\", text, \"--mode\", \"now\"], {\n stdio: \"inherit\"\n });\n } catch (err) {\n if (err?.code === \"ENOENT\") {\n throw new Error(\"Urgent wake failed: openclaw CLI not found.\");\n }\n throw new Error(`Urgent wake failed: ${err?.message || \"unknown error\"}`);\n }\n}\nasync function flush() {\n if (pendingCheckpoint) {\n clearTimeout(pendingCheckpoint);\n pendingCheckpoint = null;\n }\n if (!pendingData) return null;\n const { dir, data } = pendingData;\n pendingData = null;\n writeCheckpointToDisk(dir, data);\n return data;\n}\nasync function checkpoint(options) {\n const dir = ensureClawvaultDir(options.vaultPath);\n const data = {\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n workingOn: options.workingOn || null,\n focus: options.focus || null,\n blocked: options.blocked || null,\n urgent: options.urgent || false\n };\n const sessionState = loadSessionState(dir);\n const envState = getEnvSessionState();\n data.sessionId = sessionState?.sessionId;\n data.sessionKey = envState.sessionKey || sessionState?.sessionKey || sessionState?.sessionId;\n data.model = envState.model || sessionState?.model;\n data.tokenEstimate = envState.tokenEstimate ?? sessionState?.tokenEstimate;\n data.sessionStartedAt = sessionState?.startedAt;\n if (options.urgent) {\n if (pendingCheckpoint) {\n clearTimeout(pendingCheckpoint);\n pendingCheckpoint = null;\n }\n pendingData = null;\n writeCheckpointToDisk(dir, data);\n triggerUrgentWake(data);\n } else {\n pendingData = { dir, data };\n if (pendingCheckpoint) clearTimeout(pendingCheckpoint);\n pendingCheckpoint = setTimeout(() => {\n void flush();\n }, 1e3);\n }\n return data;\n}\nasync function clearDirtyFlag(vaultPath) {\n const flagPath = path.join(vaultPath, CLAWVAULT_DIR, DIRTY_DEATH_FLAG);\n if (fs.existsSync(flagPath)) {\n fs.unlinkSync(flagPath);\n }\n}\nasync function cleanExit(vaultPath) {\n await clearDirtyFlag(vaultPath);\n}\nasync function checkDirtyDeath(vaultPath) {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n const flagPath = path.join(dir, DIRTY_DEATH_FLAG);\n const checkpointPath = path.join(dir, CHECKPOINT_FILE);\n if (!fs.existsSync(flagPath)) {\n return { died: false, checkpoint: null, deathTime: null };\n }\n const deathTime = fs.readFileSync(flagPath, \"utf-8\").trim();\n let checkpoint2 = null;\n if (fs.existsSync(checkpointPath)) {\n try {\n checkpoint2 = JSON.parse(fs.readFileSync(checkpointPath, \"utf-8\"));\n } catch {\n }\n }\n return { died: true, checkpoint: checkpoint2, deathTime };\n}\nasync function setSessionState(vaultPath, session) {\n const dir = ensureClawvaultDir(vaultPath);\n const sessionStatePath = path.join(dir, SESSION_STATE_FILE);\n const state = typeof session === \"string\" ? { sessionId: session } : { ...session };\n if (!state.startedAt) {\n state.startedAt = (/* @__PURE__ */ new Date()).toISOString();\n }\n fs.writeFileSync(sessionStatePath, JSON.stringify(state, null, 2));\n}\n\nexport {\n flush,\n checkpoint,\n clearDirtyFlag,\n cleanExit,\n checkDirtyDeath,\n setSessionState\n};\n",837 "inputSchema": {},838 "outputSchema": null,839 "icons": null,840 "annotations": null,841 "meta": null,842 "execution": null843 },844 {845 "name": "link.js",846 "title": null,847 "description": "Script: link.js. Code:\nimport {\n autoLink,\n dryRunLink,\n findUnlinkedMentions\n} from \"../chunk-42MXU7A6.js\";\nimport {\n readBacklinksIndex,\n rebuildBacklinksIndex,\n scanVaultLinks\n} from \"../chunk-4VQTUVH7.js\";\nimport {\n getVaultPath\n} from \"../chunk-4KDZZW4X.js\";\nimport {\n buildEntityIndex\n} from \"../chunk-J7ZWCI2C.js\";\n\n// src/commands/link.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nasync function linkCommand(file, options) {\n const vaultPath = getVaultPath();\n const index = buildEntityIndex(vaultPath);\n const suggestionIndex = filterIndex(index, /* @__PURE__ */ new Set([\"people\", \"projects\", \"decisions\"]));\n const modeCount = [options.backlinks ? 1 : 0, options.orphans ? 1 : 0, options.rebuild ? 1 : 0].reduce((sum, value) => sum + value, 0);\n if (modeCount > 1) {\n console.error(\"Error: Use only one of --backlinks, --orphans, or --rebuild\");\n process.exit(1);\n }\n if (options.rebuild) {\n const result = rebuildBacklinksIndex(vaultPath, { entityIndex: index });\n const orphanSuffix = result.orphans.length > 0 ? `, ${result.orphans.length} orphan(s)` : \"\";\n console.log(`\\u2713 Rebuilt backlinks (${result.backlinks.size} targets, ${result.linkCount} links${orphanSuffix})`);\n return;\n }\n if (options.backlinks) {\n if (file) {\n console.error(\"Error: Use --backlinks without a file argument\");\n process.exit(1);\n }\n const target = resolveBacklinkTarget(options.backlinks, vaultPath, index);\n if (!target) {\n console.error(\"Error: Invalid target for --backlinks\");\n process.exit(1);\n }\n const backlinks = readBacklinksIndex(vaultPath) ?? rebuildBacklinksIndex(vaultPath, { entityIndex: index }).backlinks;\n const sources = backlinks.get(target) || [];\n if (sources.length === 0) {\n console.log(`No backlinks found for ${target}`);\n return;\n }\n console.log(`Backlinks \\u2192 ${target}`);\n for (const source of sources.sort()) {\n console.log(` - ${source}`);\n }\n return;\n }\n if (options.orphans) {\n if (file || options.all) {\n console.error(\"Error: --orphans does not accept a file or --all\");\n process.exit(1);\n }\n const result = scanVaultLinks(vaultPath, { entityIndex: index });\n if (result.orphans.length === 0) {\n console.log(\"\\u2713 No orphan links found\");\n return;\n }\n const orphans = result.orphans.slice().sort((a, b) => a.target.localeCompare(b.target) || a.source.localeCompare(b.source));\n console.log(`\\u26A0 ${orphans.length} orphan link(s) found`);\n for (const orphan of orphans) {\n console.log(` - ${orphan.source} \\u2192 [[${orphan.target}]]`);\n }\n return;\n }\n if (options.all) {\n await linkAllFiles(vaultPath, index, suggestionIndex, options.dryRun);\n return;\n }\n if (!file) {\n console.error(\"Error: Specify a file or use --all\");\n process.exit(1);\n }\n const filePath = path.isAbsolute(file) ? file : path.join(process.cwd(), file);\n if (!fs.existsSync(filePath)) {\n console.error(`Error: File not found: ${filePath}`);\n process.exit(1);\n }\n await linkFile(filePath, index, suggestionIndex, options.dryRun);\n}\nfunction filterIndex(index, categories) {\n const entries = /* @__PURE__ */ new Map();\n const byPath = /* @__PURE__ */ new Map();\n for (const [alias, targetPath] of index.entries) {\n const category = targetPath.split(\"/\")[0];\n if (categories.has(category)) {\n entries.set(alias, targetPath);\n }\n }\n for (const [targetPath, entry] of index.byPath) {\n const category = targetPath.split(\"/\")[0];\n if (categories.has(category)) {\n byPath.set(targetPath, entry);\n }\n }\n return { entries, byPath };\n}\nfunction resolveBacklinkTarget(input, vaultPath, index) {\n let target = input.trim();\n if (!target) return null;\n if (target.startsWith(\"[[\") && target.endsWith(\"]]\")) {\n target = target.slice(2, -2);\n }\n const pipeIndex = target.indexOf(\"|\");\n if (pipeIndex !== -1) {\n target = target.slice(0, pipeIndex);\n }\n const hashIndex = target.indexOf(\"#\");\n if (hashIndex !== -1) {\n target = target.slice(0, hashIndex);\n }\n target = target.trim();\n if (!target) return null;\n if (target.endsWith(\".md\")) {\n target = target.slice(0, -3);\n }\n if (target.startsWith(\"/\")) {\n target = target.slice(1);\n }\n const candidate = path.isAbsolute(target) ? target : path.join(vaultPath, target);\n const withExtension = candidate.endsWith(\".md\") ? candidate : `${candidate}.md`;\n if (fs.existsSync(candidate) && candidate.endsWith(\".md\")) {\n return toVaultId(vaultPath, candidate);\n }\n if (fs.existsSync(withExtension)) {\n return toVaultId(vaultPath, withExtension);\n }\n const aliasKey = target.toLowerCase();\n if (index.entries.has(aliasKey)) {\n return index.entries.get(aliasKey);\n }\n return target.replace(/\\\\/g, \"/\");\n}\nfunction toVaultId(vaultPath, filePath) {\n const relative2 = path.relative(vaultPath, filePath).replace(/\\.md$/, \"\");\n return relative2.split(path.sep).join(\"/\");\n}\nfunction logSuggestions(filePath, suggestions) {\n if (suggestions.length === 0) return;\n console.log(`\n\\u{1F4A1} Suggested links in ${path.basename(filePath)}`);\n for (const suggestion of suggestions) {\n console.log(` Line ${suggestion.line}: \"${suggestion.alias}\" \\u2192 [[${suggestion.path}]]`);\n }\n}\nasync function linkFile(filePath, index, suggestionIndex, dryRun) {\n const content = fs.readFileSync(filePath, \"utf-8\");\n const linkedContent = autoLink(content, index);\n const suggestions = findUnlinkedMentions(linkedContent, suggestionIndex);\n if (dryRun) {\n const matches = dryRunLink(content, index);\n if (matches.length > 0) {\n console.log(`\n\\u{1F4C4} ${filePath}`);\n for (const m of matches) {\n console.log(` Line ${m.line}: \"${m.alias}\" \\u2192 [[${m.path}]]`);\n }\n }\n logSuggestions(filePath, suggestions);\n return matches.length;\n }\n if (linkedContent !== content) {\n fs.writeFileSync(filePath, linkedContent);\n const matches = dryRunLink(content, index);\n console.log(`\\u2713 Linked ${matches.length} entities in ${path.basename(filePath)}`);\n logSuggestions(filePath, suggestions);\n return matches.length;\n }\n logSuggestions(filePath, suggestions);\n return 0;\n}\nasync function linkAllFiles(vaultPath, index, suggestionIndex, dryRun) {\n const files = [];\n function walk(dir) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (!entry.name.startsWith(\".\") && entry.name !== \"archive\" && entry.name !== \"templates\") {\n walk(fullPath);\n }\n } else if (entry.name.endsWith(\".md\")) {\n files.push(fullPath);\n }\n }\n }\n walk(vaultPath);\n let totalLinks = 0;\n let filesModified = 0;\n for (const file of files) {\n const links = await linkFile(file, index, suggestionIndex, dryRun);\n if (links > 0) {\n totalLinks += links;\n filesModified++;\n }\n }\n console.log(`\n${dryRun ? \"(dry run) \" : \"\"}${totalLinks} links in ${filesModified} files`);\n}\nexport {\n linkCommand\n};\n",848 "inputSchema": {},849 "outputSchema": null,850 "icons": null,851 "annotations": null,852 "meta": null,853 "execution": null854 },855 {856 "name": "sleep.d.ts",857 "title": null,858 "description": "Script: sleep.d.ts. Code:\nimport { H as HandoffDocument, D as Document } from '../types-DO8rJ490.js';\n\ntype PromptFn = (question: string) => Promise<string>;\ninterface SleepOptions {\n workingOn: string;\n next?: string;\n blocked?: string;\n decisions?: string;\n questions?: string;\n feeling?: string;\n sessionKey?: string;\n vaultPath: string;\n index?: boolean;\n git?: boolean;\n prompt?: PromptFn;\n cwd?: string;\n}\ninterface GitCommitResult {\n repoRoot?: string;\n dirtyCount?: number;\n committed: boolean;\n message?: string;\n skippedReason?: string;\n}\ninterface SleepResult {\n handoff: HandoffDocument;\n document: Document;\n git?: GitCommitResult;\n}\ndeclare function sleep(options: SleepOptions): Promise<SleepResult>;\n\nexport { type GitCommitResult, type PromptFn, type SleepOptions, type SleepResult, sleep };\n",859 "inputSchema": {},860 "outputSchema": null,861 "icons": null,862 "annotations": null,863 "meta": null,864 "execution": null865 },866 {867 "name": "template.d.ts",868 "title": null,869 "description": "Script: template.d.ts. Code:\nimport { TemplateVariables } from '../lib/template-engine.js';\n\ninterface TemplateCommandContext {\n vaultPath?: string;\n cwd?: string;\n builtinDir?: string;\n}\ninterface TemplateCreateOptions extends TemplateCommandContext {\n title?: string;\n type?: string;\n}\ninterface TemplateAddOptions extends TemplateCommandContext {\n name: string;\n overwrite?: boolean;\n}\ndeclare function listTemplates(options?: TemplateCommandContext): string[];\ndeclare function createFromTemplate(name: string, options?: TemplateCreateOptions): {\n outputPath: string;\n templatePath: string;\n variables: TemplateVariables;\n};\ndeclare function addTemplate(file: string, options: TemplateAddOptions): {\n templatePath: string;\n name: string;\n};\n\nexport { type TemplateAddOptions, type TemplateCommandContext, type TemplateCreateOptions, addTemplate, createFromTemplate, listTemplates };\n",870 "inputSchema": {},871 "outputSchema": null,872 "icons": null,873 "annotations": null,874 "meta": null,875 "execution": null876 },877 {878 "name": "wake.d.ts",879 "title": null,880 "description": "Script: wake.d.ts. Code:\nimport { e as SessionRecap } from '../types-DO8rJ490.js';\nimport { RecoveryInfo } from './recover.js';\nimport './checkpoint.js';\n\ninterface WakeOptions {\n vaultPath: string;\n handoffLimit?: number;\n brief?: boolean;\n}\ninterface WakeResult {\n recovery: RecoveryInfo;\n recap: SessionRecap;\n recapMarkdown: string;\n summary: string;\n}\ndeclare function buildWakeSummary(recovery: RecoveryInfo, recap: SessionRecap): string;\ndeclare function wake(options: WakeOptions): Promise<WakeResult>;\n\nexport { type WakeOptions, type WakeResult, buildWakeSummary, wake };\n",881 "inputSchema": {},882 "outputSchema": null,883 "icons": null,884 "annotations": null,885 "meta": null,886 "execution": null887 },888 {889 "name": "recover.js",890 "title": null,891 "description": "Script: recover.js. Code:\nimport {\n formatRecoveryInfo,\n recover\n} from \"../chunk-MILVYUPK.js\";\nimport \"../chunk-MZZJLQNQ.js\";\nimport \"../chunk-7ZRP733D.js\";\nexport {\n formatRecoveryInfo,\n recover\n};\n",892 "inputSchema": {},893 "outputSchema": null,894 "icons": null,895 "annotations": null,896 "meta": null,897 "execution": null898 },899 {900 "name": "doctor.js",901 "title": null,902 "description": "Script: doctor.js. Code:\nimport {\n ClawVault,\n findVault\n} from \"../chunk-MXNXWOPL.js\";\nimport {\n scanVaultLinks\n} from \"../chunk-4VQTUVH7.js\";\nimport \"../chunk-J7ZWCI2C.js\";\nimport {\n formatAge\n} from \"../chunk-7ZRP733D.js\";\nimport {\n hasQmd\n} from \"../chunk-VJIFT5T5.js\";\n\n// src/commands/doctor.ts\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nvar CLAWVAULT_DIR = \".clawvault\";\nvar CHECKPOINT_FILE = \"last-checkpoint.json\";\nvar DAY_MS = 24 * 60 * 60 * 1e3;\nvar ACTIVE_USE_DAYS = 7;\nfunction daysSince(date, now = Date.now()) {\n return Math.max(0, Math.floor((now - date.getTime()) / DAY_MS));\n}\nfunction describeAge(date, now = Date.now()) {\n return formatAge(now - date.getTime());\n}\nfunction loadCheckpointTimestamp(vaultPath) {\n const checkpointPath = path.join(vaultPath, CLAWVAULT_DIR, CHECKPOINT_FILE);\n if (!fs.existsSync(checkpointPath)) {\n return {};\n }\n try {\n const data = JSON.parse(fs.readFileSync(checkpointPath, \"utf-8\"));\n return { timestamp: data.timestamp };\n } catch (err) {\n return { error: err?.message || \"Failed to parse checkpoint\" };\n }\n}\nfunction getShellConfigPaths(shellPath) {\n const home = os.homedir();\n const shellName = shellPath ? path.basename(shellPath) : \"bash\";\n if (shellName === \"zsh\") {\n return [path.join(home, \".zshrc\"), path.join(home, \".zprofile\")];\n }\n if (shellName === \"fish\") {\n return [path.join(home, \".config\", \"fish\", \"config.fish\")];\n }\n return [path.join(home, \".bashrc\"), path.join(home, \".bash_profile\"), path.join(home, \".profile\")];\n}\nfunction hasClawvaultPathConfig(paths) {\n for (const filePath of paths) {\n if (!fs.existsSync(filePath)) continue;\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n if (/CLAWVAULT_PATH\\s*=/.test(content)) {\n return true;\n }\n } catch {\n }\n }\n return false;\n}\nasync function resolveVault(vaultPath) {\n if (vaultPath) {\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n return vault;\n }\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n const vault = new ClawVault(path.resolve(envPath));\n await vault.load();\n return vault;\n }\n const found = await findVault();\n if (!found) {\n throw new Error(\"No ClawVault found. Run `clawvault init` first.\");\n }\n return found;\n}\nasync function doctor(vaultPath) {\n const checks = [];\n let warnings = 0;\n let errors = 0;\n if (hasQmd()) {\n checks.push({ label: \"qmd installed\", status: \"ok\" });\n } else {\n checks.push({\n label: \"qmd installed\",\n status: \"error\",\n hint: \"Install qmd to enable ClawVault commands.\"\n });\n errors++;\n }\n const shellConfigs = getShellConfigPaths(process.env.SHELL).filter(fs.existsSync);\n if (hasClawvaultPathConfig(shellConfigs)) {\n checks.push({\n label: \"CLAWVAULT_PATH in shell config\",\n status: \"ok\",\n detail: shellConfigs.map((p) => path.basename(p)).join(\", \")\n });\n } else {\n checks.push({\n label: \"CLAWVAULT_PATH in shell config\",\n status: \"warn\",\n hint: \"Run `clawvault shell-init` and add it to your shell rc.\"\n });\n warnings++;\n }\n if (!hasQmd()) {\n return { vaultPath, checks, warnings, errors };\n }\n let vault;\n try {\n vault = await resolveVault(vaultPath);\n checks.push({ label: \"vault found\", status: \"ok\", detail: vault.getPath() });\n } catch (err) {\n checks.push({\n label: \"vault found\",\n status: \"error\",\n detail: err?.message || \"Unable to locate vault\"\n });\n errors++;\n return { vaultPath, checks, warnings, errors };\n }\n const stats = await vault.stats();\n const documents = await vault.list();\n const handoffs = await vault.list(\"handoffs\");\n const inbox = await vault.list(\"inbox\");\n const qmdCollection = vault.getQmdCollection();\n if (qmdCollection) {\n checks.push({ label: \"qmd collection configured\", status: \"ok\", detail: qmdCollection });\n } else {\n checks.push({\n label: \"qmd collection configured\",\n status: \"warn\",\n hint: \"Set qmd collection in .clawvault.json\"\n });\n warnings++;\n }\n const latestDoc = documents.slice().sort((a, b) => b.modified.getTime() - a.modified.getTime())[0];\n const latestDocAge = latestDoc ? daysSince(latestDoc.modified) : null;\n let lastHandoffAge = null;\n if (handoffs.length === 0) {\n checks.push({\n label: \"recent handoff\",\n status: \"warn\",\n hint: \"Run `clawvault sleep` at the end of sessions.\"\n });\n warnings++;\n } else {\n const latestHandoff = handoffs.slice().sort((a, b) => b.modified.getTime() - a.modified.getTime())[0];\n lastHandoffAge = daysSince(latestHandoff.modified);\n const ageLabel = describeAge(latestHandoff.modified);\n if (lastHandoffAge > 1) {\n checks.push({\n label: \"recent handoff\",\n status: \"warn\",\n detail: `Last handoff ${ageLabel} ago`,\n hint: \"Run `clawvault sleep` before long pauses.\"\n });\n warnings++;\n } else {\n checks.push({\n label: \"recent handoff\",\n status: \"ok\",\n detail: `Last handoff ${ageLabel} ago`\n });\n }\n }\n const checkpointInfo = loadCheckpointTimestamp(vault.getPath());\n const activeUse = latestDocAge !== null && latestDocAge <= ACTIVE_USE_DAYS || lastHandoffAge !== null && lastHandoffAge <= ACTIVE_USE_DAYS;\n if (checkpointInfo.error) {\n checks.push({\n label: \"checkpoint freshness\",\n status: \"warn\",\n detail: checkpointInfo.error\n });\n warnings++;\n } else if (!checkpointInfo.timestamp) {\n const status = activeUse ? \"warn\" : \"ok\";\n if (status === \"warn\") warnings++;\n checks.push({\n label: \"checkpoint freshness\",\n status,\n detail: activeUse ? \"No checkpoint found\" : \"No checkpoint found (vault appears inactive)\",\n hint: activeUse ? \"Run `clawvault checkpoint` during heavy work.\" : void 0\n });\n } else {\n const checkpointDate = new Date(checkpointInfo.timestamp);\n const checkpointAge = daysSince(checkpointDate);\n const ageLabel = describeAge(checkpointDate);\n if (activeUse && checkpointAge > 1) {\n checks.push({\n label: \"checkpoint freshness\",\n status: \"warn\",\n detail: `Last checkpoint ${ageLabel} ago`,\n hint: \"Checkpoint at least once per active day.\"\n });\n warnings++;\n } else {\n checks.push({\n label: \"checkpoint freshness\",\n status: \"ok\",\n detail: `Last checkpoint ${ageLabel} ago`\n });\n }\n }\n const linkScan = scanVaultLinks(vault.getPath());\n if (linkScan.orphans.length > 20) {\n checks.push({\n label: \"orphan links\",\n status: \"warn\",\n detail: `${linkScan.orphans.length} orphan link(s)`,\n hint: \"Run `clawvault link --orphans` to review.\"\n });\n warnings++;\n } else {\n checks.push({\n label: \"orphan links\",\n status: \"ok\",\n detail: `${linkScan.orphans.length} orphan link(s)`\n });\n }\n if (inbox.length > 5) {\n checks.push({\n label: \"inbox backlog\",\n status: \"warn\",\n detail: `${inbox.length} inbox item(s) pending`,\n hint: \"Process inbox items to keep memory tidy.\"\n });\n warnings++;\n } else {\n checks.push({\n label: \"inbox backlog\",\n status: \"ok\",\n detail: `${inbox.length} inbox item(s) pending`\n });\n }\n if (stats.documents < 5) {\n checks.push({\n label: \"vault activity\",\n status: \"warn\",\n detail: `${stats.documents} total documents`,\n hint: \"Start capturing decisions, lessons, and projects.\"\n });\n warnings++;\n }\n return { vaultPath: vault.getPath(), checks, warnings, errors };\n}\nexport {\n doctor\n};\n",903 "inputSchema": {},904 "outputSchema": null,905 "icons": null,906 "annotations": null,907 "meta": null,908 "execution": null909 },910 {911 "name": "entities.js",912 "title": null,913 "description": "Script: entities.js. Code:\nimport {\n getVaultPath\n} from \"../chunk-4KDZZW4X.js\";\nimport {\n buildEntityIndex\n} from \"../chunk-J7ZWCI2C.js\";\n\n// src/commands/entities.ts\nasync function entitiesCommand(options) {\n const vaultPath = getVaultPath();\n const index = buildEntityIndex(vaultPath);\n if (options.json) {\n const output = {};\n for (const [path, entry] of index.byPath) {\n output[path] = entry.aliases;\n }\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n const byFolder = {};\n for (const [path, entry] of index.byPath) {\n const folder = path.split(\"/\")[0];\n if (!byFolder[folder]) byFolder[folder] = [];\n byFolder[folder].push({ path, aliases: entry.aliases });\n }\n console.log(\"\\u{1F4DA} Linkable Entities\\n\");\n for (const [folder, entities] of Object.entries(byFolder)) {\n console.log(`## ${folder}/`);\n for (const entity of entities) {\n const name = entity.path.split(\"/\")[1];\n const otherAliases = entity.aliases.filter((a) => a.toLowerCase() !== name.toLowerCase());\n if (otherAliases.length > 0) {\n console.log(` - ${name} (${otherAliases.join(\", \")})`);\n } else {\n console.log(` - ${name}`);\n }\n }\n console.log();\n }\n console.log(`Total: ${index.byPath.size} entities, ${index.entries.size} linkable aliases`);\n}\nexport {\n entitiesCommand\n};\n",914 "inputSchema": {},915 "outputSchema": null,916 "icons": null,917 "annotations": null,918 "meta": null,919 "execution": null920 },921 {922 "name": "repair-session.js",923 "title": null,924 "description": "Script: repair-session.js. Code:\nimport {\n analyzeSession,\n repairSession\n} from \"../chunk-L53L5FCL.js\";\nimport {\n findMainSession,\n findSessionById,\n listAgents\n} from \"../chunk-AZRV2I5U.js\";\n\n// src/commands/repair-session.ts\nimport * as fs from \"fs\";\nfunction resolveSession(options) {\n const { sessionId, agentId } = options;\n if (sessionId && agentId) {\n return findSessionById(agentId, sessionId);\n }\n if (sessionId) {\n const agents = listAgents();\n for (const agent of agents) {\n const session = findSessionById(agent, sessionId);\n if (session) return session;\n }\n return null;\n }\n if (agentId) {\n return findMainSession(agentId);\n }\n const defaultAgent = process.env.OPENCLAW_AGENT_ID || \"clawdious\";\n return findMainSession(defaultAgent);\n}\nfunction formatRepairResult(result, options = {}) {\n const { dryRun = false } = options;\n const lines = [];\n lines.push(`Analyzing session: ${result.sessionId}`);\n lines.push(\"\");\n if (result.corruptedEntries.length === 0) {\n lines.push(\"\\u2705 No corruption detected. Session is clean.\");\n return lines.join(\"\\n\");\n }\n if (dryRun) {\n lines.push(`Found ${result.corruptedEntries.length} corrupted entries:`);\n } else {\n lines.push(`Found and fixed ${result.corruptedEntries.length} corrupted entries:`);\n }\n for (const entry of result.corruptedEntries) {\n const prefix = entry.type === \"aborted_tool_use\" ? \"Aborted tool_use\" : \"Orphaned tool_result\";\n lines.push(` - Line ${entry.lineNumber}: ${prefix} (id: ${entry.toolUseId})`);\n }\n if (result.parentRelinks.length > 0) {\n lines.push(\"\");\n if (dryRun) {\n lines.push(`Would relink ${result.parentRelinks.length} parent reference(s):`);\n } else {\n lines.push(`Relinked ${result.parentRelinks.length} parent reference(s):`);\n }\n for (const relink of result.parentRelinks.slice(0, 5)) {\n lines.push(` - Line ${relink.lineNumber}: parentId ${relink.oldParentId.slice(0, 8)}\\u2026 \\u2192 ${relink.newParentId === \"null\" ? \"null\" : relink.newParentId.slice(0, 8)}\\u2026`);\n }\n if (result.parentRelinks.length > 5) {\n lines.push(` ... and ${result.parentRelinks.length - 5} more`);\n }\n }\n lines.push(\"\");\n if (dryRun) {\n lines.push(`Would remove ${result.removedCount} entries, relink ${result.relinkedCount} parent references.`);\n } else {\n lines.push(`\\u2705 Session repaired: removed ${result.removedCount} entries, relinked ${result.relinkedCount} parent references`);\n if (result.backupPath) {\n const backupName = result.backupPath.split(\"/\").pop();\n lines.push(`Backup saved: ${backupName}`);\n }\n }\n return lines.join(\"\\n\");\n}\nasync function repairSessionCommand(options) {\n const { backup = true, dryRun = false } = options;\n const session = resolveSession(options);\n if (!session) {\n throw new Error(\n options.sessionId ? `Session not found: ${options.sessionId}` : options.agentId ? `No main session found for agent: ${options.agentId}` : \"No session found. Specify --session or --agent.\"\n );\n }\n if (!fs.existsSync(session.filePath)) {\n throw new Error(`Session file not found: ${session.filePath}`);\n }\n if (dryRun) {\n return analyzeSession(session.filePath);\n }\n return repairSession(session.filePath, { backup, dryRun: false });\n}\nfunction listAgentSessions(agentId) {\n const agents = agentId ? [agentId] : listAgents();\n const lines = [];\n if (agents.length === 0) {\n return \"No agents found in ~/.openclaw/agents/\";\n }\n for (const agent of agents) {\n const mainSession = findMainSession(agent);\n if (mainSession) {\n lines.push(`${agent}:`);\n lines.push(` Main session: ${mainSession.sessionId}`);\n lines.push(` File: ${mainSession.filePath}`);\n if (mainSession.updatedAt) {\n const date = new Date(mainSession.updatedAt);\n lines.push(` Updated: ${date.toISOString()}`);\n }\n lines.push(\"\");\n }\n }\n if (lines.length === 0) {\n return agentId ? `No sessions found for agent: ${agentId}` : \"No sessions found.\";\n }\n return lines.join(\"\\n\");\n}\nexport {\n formatRepairResult,\n listAgentSessions,\n repairSessionCommand,\n resolveSession\n};\n",925 "inputSchema": {},926 "outputSchema": null,927 "icons": null,928 "annotations": null,929 "meta": null,930 "execution": null931 },932 {933 "name": "shell-init.d.ts",934 "title": null,935 "description": "Script: shell-init.d.ts. Code:\ninterface ShellInitOptions {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n}\ndeclare function shellInit(options?: ShellInitOptions): string;\n\nexport { type ShellInitOptions, shellInit };\n",936 "inputSchema": {},937 "outputSchema": null,938 "icons": null,939 "annotations": null,940 "meta": null,941 "execution": null942 },943 {944 "name": "link.d.ts",945 "title": null,946 "description": "Script: link.d.ts. Code:\ninterface LinkOptions {\n all?: boolean;\n dryRun?: boolean;\n backlinks?: string;\n orphans?: boolean;\n rebuild?: boolean;\n}\ndeclare function linkCommand(file: string | undefined, options: LinkOptions): Promise<void>;\n\nexport { linkCommand };\n",947 "inputSchema": {},948 "outputSchema": null,949 "icons": null,950 "annotations": null,951 "meta": null,952 "execution": null953 },954 {955 "name": "wake.js",956 "title": null,957 "description": "Script: wake.js. Code:\nimport {\n ClawVault\n} from \"../chunk-MXNXWOPL.js\";\nimport {\n recover\n} from \"../chunk-MILVYUPK.js\";\nimport {\n clearDirtyFlag\n} from \"../chunk-MZZJLQNQ.js\";\nimport \"../chunk-7ZRP733D.js\";\nimport \"../chunk-VJIFT5T5.js\";\n\n// src/commands/wake.ts\nimport * as path from \"path\";\nvar DEFAULT_HANDOFF_LIMIT = 3;\nfunction formatSummaryItems(items, maxItems = 2) {\n const cleaned = items.map((item) => item.trim()).filter(Boolean);\n if (cleaned.length === 0) return \"\";\n if (cleaned.length <= maxItems) return cleaned.join(\", \");\n return `${cleaned.slice(0, maxItems).join(\", \")} +${cleaned.length - maxItems} more`;\n}\nfunction buildWakeSummary(recovery, recap) {\n if (recovery.checkpoint?.workingOn) {\n return recovery.checkpoint.workingOn;\n }\n const latestHandoff = recap.recentHandoffs[0];\n if (latestHandoff?.workingOn?.length) {\n return formatSummaryItems(latestHandoff.workingOn);\n }\n if (recap.activeProjects.length > 0) {\n return formatSummaryItems(recap.activeProjects);\n }\n return \"No recent work summary found.\";\n}\nasync function wake(options) {\n const vaultPath = path.resolve(options.vaultPath);\n const recovery = await recover(vaultPath, { clearFlag: true });\n await clearDirtyFlag(vaultPath);\n const vault = new ClawVault(vaultPath);\n await vault.load();\n const recap = await vault.generateRecap({\n handoffLimit: options.handoffLimit ?? DEFAULT_HANDOFF_LIMIT,\n brief: options.brief ?? true\n });\n const summary = buildWakeSummary(recovery, recap);\n const recapMarkdown = vault.formatRecap(recap, { brief: options.brief ?? true });\n return {\n recovery,\n recap,\n recapMarkdown,\n summary\n };\n}\nexport {\n buildWakeSummary,\n wake\n};\n",958 "inputSchema": {},959 "outputSchema": null,960 "icons": null,961 "annotations": null,962 "meta": null,963 "execution": null964 },965 {966 "name": "recover.d.ts",967 "title": null,968 "description": "Script: recover.d.ts. Code:\nimport { CheckpointData } from './checkpoint.js';\n\n/**\n * Recovery command - detect dirty death and provide recovery info\n */\n\ninterface RecoveryInfo {\n died: boolean;\n deathTime: string | null;\n checkpoint: CheckpointData | null;\n handoffPath: string | null;\n handoffContent: string | null;\n recoveryMessage: string;\n}\ndeclare function recover(vaultPath: string, options?: {\n clearFlag?: boolean;\n verbose?: boolean;\n}): Promise<RecoveryInfo>;\n/**\n * Format recovery info for CLI output\n */\ndeclare function formatRecoveryInfo(info: RecoveryInfo, options?: {\n verbose?: boolean;\n}): string;\n\nexport { type RecoveryInfo, formatRecoveryInfo, recover };\n",969 "inputSchema": {},970 "outputSchema": null,971 "icons": null,972 "annotations": null,973 "meta": null,974 "execution": null975 },976 {977 "name": "shell-init.js",978 "title": null,979 "description": "Script: shell-init.js. Code:\n// src/commands/shell-init.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nfunction detectVaultPath(startPath) {\n let current = path.resolve(startPath);\n while (true) {\n const configPath = path.join(current, \".clawvault.json\");\n if (fs.existsSync(configPath)) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\nfunction shellQuote(value) {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\nfunction shellInit(options = {}) {\n const env = options.env ?? process.env;\n const cwd = options.cwd ?? process.cwd();\n const detected = env.CLAWVAULT_PATH || detectVaultPath(cwd);\n const lines = [];\n lines.push(\"# ClawVault shell integration\");\n if (detected) {\n lines.push('if [ -z \"$CLAWVAULT_PATH\" ]; then');\n lines.push(` export CLAWVAULT_PATH=${shellQuote(path.resolve(detected))}`);\n lines.push(\"fi\");\n } else {\n lines.push(\"# Set CLAWVAULT_PATH to your vault directory:\");\n lines.push('# export CLAWVAULT_PATH=\"/path/to/vault\"');\n }\n lines.push(\"alias cvwake='clawvault wake'\");\n lines.push(\"alias cvsleep='clawvault sleep'\");\n lines.push(\"alias cvcheck='clawvault doctor'\");\n return lines.join(\"\\n\");\n}\nexport {\n shellInit\n};\n",980 "inputSchema": {},981 "outputSchema": null,982 "icons": null,983 "annotations": null,984 "meta": null,985 "execution": null986 },987 {988 "name": "status.js",989 "title": null,990 "description": "Script: status.js. Code:\nimport {\n ClawVault\n} from \"../chunk-MXNXWOPL.js\";\nimport {\n scanVaultLinks\n} from \"../chunk-4VQTUVH7.js\";\nimport \"../chunk-J7ZWCI2C.js\";\nimport {\n formatAge\n} from \"../chunk-7ZRP733D.js\";\nimport {\n QmdUnavailableError,\n hasQmd\n} from \"../chunk-VJIFT5T5.js\";\n\n// src/commands/status.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { execFileSync } from \"child_process\";\nvar CLAWVAULT_DIR = \".clawvault\";\nvar CHECKPOINT_FILE = \"last-checkpoint.json\";\nvar DIRTY_DEATH_FLAG = \"dirty-death.flag\";\nfunction findGitRoot(startPath) {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, \".git\"))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\nfunction getGitStatus(repoRoot) {\n const output = execFileSync(\"git\", [\"-C\", repoRoot, \"status\", \"--porcelain\"], {\n encoding: \"utf-8\"\n });\n const lines = output.split(\"\\n\").filter(Boolean);\n return { clean: lines.length === 0, dirtyCount: lines.length };\n}\nfunction parseQmdCollectionsText(raw) {\n const names = [];\n const regex = /^(\\S+)\\s+\\(qmd:\\/\\/\\1\\/\\)/gm;\n let match;\n while ((match = regex.exec(raw)) !== null) {\n names.push(match[1]);\n }\n return names;\n}\nfunction getQmdIndexStatus(collection, root) {\n const output = execFileSync(\"qmd\", [\"collection\", \"list\"], { encoding: \"utf-8\" });\n const names = parseQmdCollectionsText(output);\n if (names.includes(collection)) {\n return \"present\";\n }\n return \"missing\";\n}\nfunction loadCheckpoint(vaultPath) {\n const checkpointPath = path.join(vaultPath, CLAWVAULT_DIR, CHECKPOINT_FILE);\n if (!fs.existsSync(checkpointPath)) {\n return { data: null };\n }\n try {\n const data = JSON.parse(fs.readFileSync(checkpointPath, \"utf-8\"));\n return { data };\n } catch (err) {\n return { data: null, error: err?.message || \"Failed to parse checkpoint\" };\n }\n}\nasync function getStatus(vaultPath) {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n const stats = await vault.stats();\n const linkScan = scanVaultLinks(vault.getPath());\n const issues = [];\n const checkpointInfo = loadCheckpoint(vault.getPath());\n const checkpoint = checkpointInfo.data;\n if (checkpointInfo.error) {\n issues.push(`Checkpoint parse error: ${checkpointInfo.error}`);\n }\n const checkpointStatus = {\n exists: Boolean(checkpoint),\n timestamp: checkpoint?.timestamp,\n age: checkpoint?.timestamp ? formatAge(Date.now() - new Date(checkpoint.timestamp).getTime()) : void 0,\n sessionKey: checkpoint?.sessionKey,\n model: checkpoint?.model,\n tokenEstimate: checkpoint?.tokenEstimate\n };\n if (!checkpointStatus.exists) {\n issues.push(\"No checkpoint found\");\n }\n const dirtyFlagPath = path.join(vault.getPath(), CLAWVAULT_DIR, DIRTY_DEATH_FLAG);\n if (fs.existsSync(dirtyFlagPath)) {\n issues.push(\"Dirty death flag is set\");\n }\n const qmdCollection = vault.getQmdCollection();\n const qmdRoot = vault.getQmdRoot();\n let qmdIndexStatus = \"missing\";\n let qmdError;\n try {\n qmdIndexStatus = getQmdIndexStatus(qmdCollection, qmdRoot);\n if (qmdIndexStatus !== \"present\") {\n issues.push(`qmd collection ${qmdIndexStatus.replace(\"-\", \" \")}`);\n }\n } catch (err) {\n qmdError = err?.message || \"Failed to check qmd index\";\n issues.push(`qmd status error: ${qmdError}`);\n }\n let gitStatus;\n const gitRoot = findGitRoot(vault.getPath());\n if (gitRoot) {\n try {\n const gitInfo = getGitStatus(gitRoot);\n gitStatus = { repoRoot: gitRoot, ...gitInfo };\n if (!gitInfo.clean) {\n issues.push(`Uncommitted changes: ${gitInfo.dirtyCount}`);\n }\n } catch (err) {\n issues.push(`Git status error: ${err?.message || \"unknown error\"}`);\n }\n }\n return {\n vaultName: vault.getName(),\n vaultPath: vault.getPath(),\n health: issues.length === 0 ? \"ok\" : \"warning\",\n issues,\n checkpoint: checkpointStatus,\n qmd: {\n collection: qmdCollection,\n root: qmdRoot,\n indexStatus: qmdIndexStatus,\n error: qmdError\n },\n git: gitStatus,\n links: {\n total: linkScan.linkCount,\n orphans: linkScan.orphans.length\n },\n documents: stats.documents,\n categories: stats.categories\n };\n}\nfunction formatStatus(status) {\n let output = \"ClawVault Status\\n\";\n output += \"-\".repeat(40) + \"\\n\";\n output += `Vault: ${status.vaultName}\n`;\n output += `Path: ${status.vaultPath}\n`;\n output += `Health: ${status.health}\n`;\n if (status.issues.length > 0) {\n output += `Issues: ${status.issues.join(\"; \")}\n`;\n } else {\n output += \"Issues: none\\n\";\n }\n output += \"\\nCheckpoint:\\n\";\n if (!status.checkpoint.exists) {\n output += \" - none\\n\";\n } else {\n output += ` - Timestamp: ${status.checkpoint.timestamp}\n`;\n if (status.checkpoint.age) {\n output += ` - Age: ${status.checkpoint.age}\n`;\n }\n if (status.checkpoint.sessionKey) {\n output += ` - Session key: ${status.checkpoint.sessionKey}\n`;\n }\n if (status.checkpoint.model) {\n output += ` - Model: ${status.checkpoint.model}\n`;\n }\n if (status.checkpoint.tokenEstimate !== void 0) {\n output += ` - Token estimate: ${status.checkpoint.tokenEstimate}\n`;\n }\n }\n output += \"\\nqmd:\\n\";\n output += ` - Collection: ${status.qmd.collection}\n`;\n output += ` - Root: ${status.qmd.root}\n`;\n output += ` - Index: ${status.qmd.indexStatus}\n`;\n if (status.qmd.error) {\n output += ` - Error: ${status.qmd.error}\n`;\n }\n if (status.git) {\n output += \"\\nGit:\\n\";\n output += ` - Repo: ${status.git.repoRoot}\n`;\n output += ` - Status: ${status.git.clean ? \"clean\" : \"dirty\"} (${status.git.dirtyCount} change(s))\n`;\n }\n output += \"\\nLinks:\\n\";\n output += ` - Total: ${status.links.total}\n`;\n if (status.links.orphans > 0) {\n output += ` - Orphans: ${status.links.orphans}\n`;\n }\n output += \"\\nDocuments:\\n\";\n output += ` - Total: ${status.documents}\n`;\n output += \" - By category:\\n\";\n for (const [category, count] of Object.entries(status.categories)) {\n output += ` * ${category}: ${count}\n`;\n }\n output += \"-\".repeat(40) + \"\\n\";\n return output;\n}\nasync function statusCommand(vaultPath, options = {}) {\n const status = await getStatus(vaultPath);\n if (options.json) {\n console.log(JSON.stringify(status, null, 2));\n return;\n }\n console.log(formatStatus(status));\n}\nexport {\n formatStatus,\n getStatus,\n statusCommand\n};\n",991 "inputSchema": {},992 "outputSchema": null,993 "icons": null,994 "annotations": null,995 "meta": null,996 "execution": null997 },998 {999 "name": "template.js",1000 "title": null,1001 "description": "Script: template.js. Code:\nimport {\n buildTemplateVariables,\n renderTemplate\n} from \"../chunk-7766SIJP.js\";\n\n// src/commands/template.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { fileURLToPath } from \"url\";\nvar VAULT_CONFIG_FILE = \".clawvault.json\";\nvar TEMPLATE_EXTENSION = \".md\";\nfunction resolveBuiltinTemplatesDir(override) {\n if (override) {\n const resolved = path.resolve(override);\n return fs.existsSync(resolved) ? resolved : null;\n }\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(moduleDir, \"../templates\"),\n path.resolve(moduleDir, \"../../templates\")\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {\n return candidate;\n }\n }\n return null;\n}\nfunction findVaultRoot(start) {\n let current = path.resolve(start);\n while (true) {\n if (fs.existsSync(path.join(current, VAULT_CONFIG_FILE))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\nfunction resolveVaultPath(options) {\n if (options.vaultPath) {\n return path.resolve(options.vaultPath);\n }\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n return path.resolve(envPath);\n }\n const cwd = options.cwd ?? process.cwd();\n return findVaultRoot(cwd);\n}\nfunction normalizeTemplateName(name) {\n const base = path.basename(name, path.extname(name));\n return base.trim();\n}\nfunction slugify(text) {\n return text.toLowerCase().replace(/[^\\w\\s-]/g, \"\").replace(/\\s+/g, \"-\").replace(/-+/g, \"-\").trim();\n}\nfunction listTemplateFiles(dir, ignore) {\n const entries = /* @__PURE__ */ new Map();\n if (!fs.existsSync(dir)) return entries;\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(TEMPLATE_EXTENSION)) continue;\n const name = normalizeTemplateName(entry.name);\n if (!name) continue;\n if (ignore?.has(name)) continue;\n entries.set(name, path.join(dir, entry.name));\n }\n return entries;\n}\nfunction buildTemplateIndex(options) {\n const index = /* @__PURE__ */ new Map();\n const builtinDir = resolveBuiltinTemplatesDir(options.builtinDir);\n if (builtinDir) {\n const ignore = /* @__PURE__ */ new Set([\"daily\"]);\n for (const [name, filePath] of listTemplateFiles(builtinDir, ignore)) {\n index.set(name, filePath);\n }\n }\n const vaultPath = resolveVaultPath(options);\n if (vaultPath) {\n const vaultTemplatesDir = path.join(vaultPath, \"templates\");\n for (const [name, filePath] of listTemplateFiles(vaultTemplatesDir)) {\n index.set(name, filePath);\n }\n }\n return index;\n}\nfunction listTemplates(options = {}) {\n const index = buildTemplateIndex(options);\n return [...index.keys()].sort();\n}\nfunction createFromTemplate(name, options = {}) {\n const templateName = normalizeTemplateName(name);\n if (!templateName) {\n throw new Error(\"Template name is required.\");\n }\n const index = buildTemplateIndex(options);\n const templatePath = index.get(templateName);\n if (!templatePath) {\n const available = [...index.keys()].sort();\n const hint = available.length > 0 ? ` Available: ${available.join(\", \")}` : \"\";\n throw new Error(`Template not found: ${templateName}.${hint}`);\n }\n const raw = fs.readFileSync(templatePath, \"utf-8\");\n const now = /* @__PURE__ */ new Date();\n const date = now.toISOString().split(\"T\")[0];\n const type = options.type ?? templateName;\n const title = options.title ?? `${type} ${date}`.trim();\n const variables = buildTemplateVariables({ title, type, date }, now);\n const rendered = renderTemplate(raw, variables);\n const cwd = options.cwd ?? process.cwd();\n const slug = slugify(title) || slugify(templateName) || `template-${date}`;\n const outputPath = path.join(cwd, `${slug}${TEMPLATE_EXTENSION}`);\n if (fs.existsSync(outputPath)) {\n throw new Error(`File already exists: ${outputPath}`);\n }\n fs.writeFileSync(outputPath, rendered);\n return { outputPath, templatePath, variables };\n}\nfunction addTemplate(file, options) {\n const name = normalizeTemplateName(options.name);\n if (!name) {\n throw new Error(\"Template name is required.\");\n }\n const vaultPath = resolveVaultPath(options);\n if (!vaultPath) {\n throw new Error(\"No vault found. Set CLAWVAULT_PATH or use --vault.\");\n }\n const cwd = options.cwd ?? process.cwd();\n const sourcePath = path.resolve(cwd, file);\n if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isFile()) {\n throw new Error(`Template file not found: ${sourcePath}`);\n }\n const templatesDir = path.join(vaultPath, \"templates\");\n fs.mkdirSync(templatesDir, { recursive: true });\n const targetPath = path.join(templatesDir, `${name}${TEMPLATE_EXTENSION}`);\n if (fs.existsSync(targetPath) && !options.overwrite) {\n throw new Error(`Template already exists: ${targetPath}`);\n }\n fs.copyFileSync(sourcePath, targetPath);\n return { templatePath: targetPath, name };\n}\nexport {\n addTemplate,\n createFromTemplate,\n listTemplates\n};\n",1002 "inputSchema": {},1003 "outputSchema": null,1004 "icons": null,1005 "annotations": null,1006 "meta": null,1007 "execution": null1008 },1009 {1010 "name": "repair-session.d.ts",1011 "title": null,1012 "description": "Script: repair-session.d.ts. Code:\nimport { SessionInfo } from '../lib/session-utils.js';\nimport { RepairResult } from '../lib/session-repair.js';\n\n/**\n * repair-session command - Repair corrupted OpenClaw session transcripts\n *\n * Fixes issues like:\n * - Aborted tool calls with partial JSON\n * - Orphaned tool_result messages referencing non-existent tool_use IDs\n * - Broken parent chain references\n */\n\ninterface RepairSessionOptions {\n sessionId?: string;\n agentId?: string;\n backup?: boolean;\n dryRun?: boolean;\n}\n/**\n * Resolve the session to repair\n */\ndeclare function resolveSession(options: RepairSessionOptions): SessionInfo | null;\n/**\n * Format repair result for CLI output\n */\ndeclare function formatRepairResult(result: RepairResult, options?: {\n dryRun?: boolean;\n}): string;\n/**\n * Main repair-session command handler\n */\ndeclare function repairSessionCommand(options: RepairSessionOptions): Promise<RepairResult>;\n/**\n * List available sessions for an agent (for --list flag)\n */\ndeclare function listAgentSessions(agentId?: string): string;\n\nexport { type RepairSessionOptions, formatRepairResult, listAgentSessions, repairSessionCommand, resolveSession };\n",1013 "inputSchema": {},1014 "outputSchema": null,1015 "icons": null,1016 "annotations": null,1017 "meta": null,1018 "execution": null1019 },1020 {1021 "name": "status.d.ts",1022 "title": null,1023 "description": "Script: status.d.ts. Code:\ninterface VaultStatus {\n vaultName: string;\n vaultPath: string;\n health: 'ok' | 'warning';\n issues: string[];\n checkpoint: {\n exists: boolean;\n timestamp?: string;\n age?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n };\n qmd: {\n collection: string;\n root: string;\n indexStatus: 'present' | 'missing' | 'root-mismatch';\n error?: string;\n };\n git?: {\n repoRoot: string;\n clean: boolean;\n dirtyCount: number;\n };\n links: {\n total: number;\n orphans: number;\n };\n documents: number;\n categories: Record<string, number>;\n}\ndeclare function getStatus(vaultPath: string): Promise<VaultStatus>;\ndeclare function formatStatus(status: VaultStatus): string;\ndeclare function statusCommand(vaultPath: string, options?: {\n json?: boolean;\n}): Promise<void>;\n\nexport { type VaultStatus, formatStatus, getStatus, statusCommand };\n",1024 "inputSchema": {},1025 "outputSchema": null,1026 "icons": null,1027 "annotations": null,1028 "meta": null,1029 "execution": null1030 },1031 {1032 "name": "setup.d.ts",1033 "title": null,1034 "description": "Script: setup.d.ts. Code:\ndeclare function setupCommand(): Promise<void>;\n\nexport { setupCommand };\n",1035 "inputSchema": {},1036 "outputSchema": null,1037 "icons": null,1038 "annotations": null,1039 "meta": null,1040 "execution": null1041 },1042 {1043 "name": "entities.d.ts",1044 "title": null,1045 "description": "Script: entities.d.ts. Code:\ninterface EntitiesOptions {\n json?: boolean;\n}\ndeclare function entitiesCommand(options: EntitiesOptions): Promise<void>;\n\nexport { entitiesCommand };\n",1046 "inputSchema": {},1047 "outputSchema": null,1048 "icons": null,1049 "annotations": null,1050 "meta": null,1051 "execution": null1052 },1053 {1054 "name": "doctor.d.ts",1055 "title": null,1056 "description": "Script: doctor.d.ts. Code:\ntype DoctorStatus = 'ok' | 'warn' | 'error';\ninterface DoctorCheck {\n label: string;\n status: DoctorStatus;\n detail?: string;\n hint?: string;\n}\ninterface DoctorReport {\n vaultPath?: string;\n checks: DoctorCheck[];\n warnings: number;\n errors: number;\n}\ndeclare function doctor(vaultPath?: string): Promise<DoctorReport>;\n\nexport { type DoctorCheck, type DoctorReport, type DoctorStatus, doctor };\n",1057 "inputSchema": {},1058 "outputSchema": null,1059 "icons": null,1060 "annotations": null,1061 "meta": null,1062 "execution": null1063 },1064 {1065 "name": "checkpoint.d.ts",1066 "title": null,1067 "description": "Script: checkpoint.d.ts. Code:\n/**\n * Quick checkpoint command - fast state save for context death resilience\n */\ninterface CheckpointOptions {\n workingOn?: string;\n focus?: string;\n blocked?: string;\n vaultPath: string;\n urgent?: boolean;\n}\ninterface CheckpointData {\n timestamp: string;\n workingOn: string | null;\n focus: string | null;\n blocked: string | null;\n sessionId?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n sessionStartedAt?: string;\n urgent?: boolean;\n}\ninterface SessionState {\n sessionId?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n startedAt?: string;\n}\ndeclare function flush(): Promise<CheckpointData | null>;\ndeclare function checkpoint(options: CheckpointOptions): Promise<CheckpointData>;\ndeclare function clearDirtyFlag(vaultPath: string): Promise<void>;\ndeclare function cleanExit(vaultPath: string): Promise<void>;\ndeclare function checkDirtyDeath(vaultPath: string): Promise<{\n died: boolean;\n checkpoint: CheckpointData | null;\n deathTime: string | null;\n}>;\ndeclare function setSessionState(vaultPath: string, session: string | SessionState): Promise<void>;\n\nexport { type CheckpointData, type CheckpointOptions, type SessionState, checkDirtyDeath, checkpoint, cleanExit, clearDirtyFlag, flush, setSessionState };\n",1068 "inputSchema": {},1069 "outputSchema": null,1070 "icons": null,1071 "annotations": null,1072 "meta": null,1073 "execution": null1074 },1075 {1076 "name": "setup.js",1077 "title": null,1078 "description": "Script: setup.js. Code:\nimport {\n setupCommand\n} from \"../chunk-QYJI73KF.js\";\nimport \"../chunk-VJIFT5T5.js\";\nexport {\n setupCommand\n};\n",1079 "inputSchema": {},1080 "outputSchema": null,1081 "icons": null,1082 "annotations": null,1083 "meta": null,1084 "execution": null1085 },1086 {1087 "name": "checkpoint.js",1088 "title": null,1089 "description": "Script: checkpoint.js. Code:\nimport {\n checkDirtyDeath,\n checkpoint,\n cleanExit,\n clearDirtyFlag,\n flush,\n setSessionState\n} from \"../chunk-MZZJLQNQ.js\";\nexport {\n checkDirtyDeath,\n checkpoint,\n cleanExit,\n clearDirtyFlag,\n flush,\n setSessionState\n};\n",1090 "inputSchema": {},1091 "outputSchema": null,1092 "icons": null,1093 "annotations": null,1094 "meta": null,1095 "execution": null1096 },1097 {1098 "name": "sleep.js",1099 "title": null,1100 "description": "Script: sleep.js. Code:\nimport {\n ClawVault\n} from \"../chunk-MXNXWOPL.js\";\nimport {\n clearDirtyFlag\n} from \"../chunk-MZZJLQNQ.js\";\nimport {\n qmdUpdate\n} from \"../chunk-VJIFT5T5.js\";\n\n// src/commands/sleep.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as readline from \"readline\";\nimport { execFileSync } from \"child_process\";\nfunction isInteractive() {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\nasync function defaultPrompt(question) {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve2) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve2(answer.trim());\n });\n });\n}\nfunction parseList(raw) {\n if (!raw) return [];\n return raw.split(\",\").map((item) => item.trim()).filter(Boolean);\n}\nfunction ensureNonEmpty(label, items) {\n if (items.length === 0) {\n throw new Error(`${label} is required.`);\n }\n}\nasync function promptForList(label, prompt, interactive) {\n if (!interactive) return [];\n const answer = await prompt(`${label} (comma-separated, empty to skip): `);\n return parseList(answer);\n}\nfunction findGitRoot(startPath) {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, \".git\"))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\nfunction getGitStatus(repoRoot) {\n const output = execFileSync(\"git\", [\"-C\", repoRoot, \"status\", \"--porcelain\"], {\n encoding: \"utf-8\"\n });\n const lines = output.split(\"\\n\").filter(Boolean);\n return { clean: lines.length === 0, dirtyCount: lines.length };\n}\nfunction isAffirmative(input) {\n const normalized = input.trim().toLowerCase();\n return normalized === \"y\" || normalized === \"yes\";\n}\nasync function maybeCommitDirtyRepo(options) {\n if (!options.enabled) {\n return { committed: false, skippedReason: \"disabled\" };\n }\n const repoRoot = findGitRoot(options.cwd);\n if (!repoRoot) {\n return { committed: false, skippedReason: \"no-repo\" };\n }\n let status;\n try {\n status = getGitStatus(repoRoot);\n } catch (err) {\n if (err?.code === \"ENOENT\") {\n return { committed: false, skippedReason: \"git-missing\" };\n }\n return { repoRoot, committed: false, skippedReason: \"status-error\" };\n }\n if (status.clean) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: \"clean\" };\n }\n if (!options.interactive) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: \"non-interactive\" };\n }\n const confirm = await options.prompt(\n `Git repo dirty (${status.dirtyCount} change(s)). Commit before sleep? (y/N): `\n );\n if (!isAffirmative(confirm)) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: \"declined\" };\n }\n const message = await options.prompt(\"Commit message: \");\n if (!message) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: \"no-message\" };\n }\n try {\n execFileSync(\"git\", [\"-C\", repoRoot, \"add\", \"-A\"], { stdio: \"inherit\" });\n execFileSync(\"git\", [\"-C\", repoRoot, \"commit\", \"-m\", message], { stdio: \"inherit\" });\n } catch (err) {\n throw new Error(`Git commit failed: ${err?.message || \"unknown error\"}`);\n }\n return {\n repoRoot,\n dirtyCount: status.dirtyCount,\n committed: true,\n message\n };\n}\nasync function sleep(options) {\n const prompt = options.prompt ?? defaultPrompt;\n const interactive = isInteractive();\n const workingOn = parseList(options.workingOn);\n ensureNonEmpty(\"Working-on summary\", workingOn);\n const nextProvided = options.next !== void 0;\n const blockedProvided = options.blocked !== void 0;\n let nextSteps = parseList(options.next);\n let blocked = parseList(options.blocked);\n if (!nextProvided) {\n nextSteps = await promptForList(\"Next steps\", prompt, interactive);\n }\n if (!blockedProvided) {\n blocked = await promptForList(\"Blocked items\", prompt, interactive);\n }\n const decisions = parseList(options.decisions);\n const questions = parseList(options.questions);\n const vault = new ClawVault(path.resolve(options.vaultPath));\n await vault.load();\n const handoffInput = {\n workingOn,\n blocked,\n nextSteps,\n decisions: decisions.length > 0 ? decisions : void 0,\n openQuestions: questions.length > 0 ? questions : void 0,\n feeling: options.feeling,\n sessionKey: options.sessionKey\n };\n const document = await vault.createHandoff(handoffInput);\n const handoff = {\n ...handoffInput,\n created: document.modified.toISOString()\n };\n await clearDirtyFlag(vault.getPath());\n if (options.index) {\n qmdUpdate(vault.getQmdCollection());\n }\n const git = await maybeCommitDirtyRepo({\n enabled: options.git !== false,\n prompt,\n cwd: options.cwd ?? process.cwd(),\n interactive\n });\n return { handoff, document, git };\n}\nexport {\n sleep\n};\n",1101 "inputSchema": {},1102 "outputSchema": null,1103 "icons": null,1104 "annotations": null,1105 "meta": null,1106 "execution": null1107 },1108 {1109 "name": "chunk-MILVYUPK.js",1110 "title": null,1111 "description": "Script: chunk-MILVYUPK.js. Code:\nimport {\n checkDirtyDeath,\n clearDirtyFlag\n} from \"./chunk-MZZJLQNQ.js\";\nimport {\n formatAge\n} from \"./chunk-7ZRP733D.js\";\n\n// src/commands/recover.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nasync function recover(vaultPath, options = {}) {\n const { clearFlag = false } = options;\n const { died, checkpoint, deathTime } = await checkDirtyDeath(vaultPath);\n if (!died) {\n return {\n died: false,\n deathTime: null,\n checkpoint: null,\n handoffPath: null,\n handoffContent: null,\n recoveryMessage: \"No context death detected. Clean startup.\"\n };\n }\n const handoffsDir = path.join(vaultPath, \"handoffs\");\n let handoffPath = null;\n let handoffContent = null;\n if (fs.existsSync(handoffsDir)) {\n const files = fs.readdirSync(handoffsDir).filter((f) => f.startsWith(\"handoff-\") && f.endsWith(\".md\")).sort().reverse();\n if (files.length > 0) {\n handoffPath = path.join(handoffsDir, files[0]);\n handoffContent = fs.readFileSync(handoffPath, \"utf-8\");\n }\n }\n let message = \"\\u26A0\\uFE0F **CONTEXT DEATH DETECTED**\\n\\n\";\n message += `Your previous session died at ${deathTime}.\n\n`;\n if (checkpoint) {\n message += \"**Last known state:**\\n\";\n if (checkpoint.workingOn) {\n message += `- Working on: ${checkpoint.workingOn}\n`;\n }\n if (checkpoint.focus) {\n message += `- Focus: ${checkpoint.focus}\n`;\n }\n if (checkpoint.blocked) {\n message += `- Blocked: ${checkpoint.blocked}\n`;\n }\n message += \"\\n\";\n }\n if (handoffPath) {\n message += `**Last handoff:** ${path.basename(handoffPath)}\n`;\n message += \"Review and resume from where you left off.\\n\";\n } else {\n message += \"**No handoff found.** You may have lost context.\\n\";\n }\n if (clearFlag) {\n await clearDirtyFlag(vaultPath);\n }\n return {\n died: true,\n deathTime,\n checkpoint,\n handoffPath,\n handoffContent,\n recoveryMessage: message\n };\n}\nfunction formatRecoveryInfo(info, options = {}) {\n const { verbose = false } = options;\n if (!info.died) {\n return \"\\u2713 Clean startup - no context death detected.\";\n }\n let output = \"\\n\\u26A0\\uFE0F CONTEXT DEATH DETECTED\\n\";\n output += \"\\u2550\".repeat(40) + \"\\n\\n\";\n output += `Death time: ${info.deathTime}\n`;\n if (info.checkpoint?.timestamp) {\n const age = formatAge(Date.now() - new Date(info.checkpoint.timestamp).getTime());\n output += `Checkpoint: ${info.checkpoint.timestamp} (${age} ago)\n`;\n }\n output += \"\\n\";\n if (info.checkpoint) {\n output += \"Last checkpoint:\\n\";\n if (info.checkpoint.workingOn) {\n output += ` \\u2022 Working on: ${info.checkpoint.workingOn}\n`;\n }\n if (info.checkpoint.focus) {\n output += ` \\u2022 Focus: ${info.checkpoint.focus}\n`;\n }\n if (info.checkpoint.blocked) {\n output += ` \\u2022 Blocked: ${info.checkpoint.blocked}\n`;\n }\n if (info.checkpoint.sessionKey || info.checkpoint.model || info.checkpoint.tokenEstimate !== void 0) {\n output += \" \\u2022 Session:\\n\";\n if (info.checkpoint.sessionKey) {\n output += ` - Key: ${info.checkpoint.sessionKey}\n`;\n }\n if (info.checkpoint.model) {\n output += ` - Model: ${info.checkpoint.model}\n`;\n }\n if (info.checkpoint.tokenEstimate !== void 0) {\n output += ` - Token estimate: ${info.checkpoint.tokenEstimate}\n`;\n }\n }\n output += \"\\n\";\n } else {\n output += \"No checkpoint data found.\\n\\n\";\n }\n if (info.handoffPath) {\n output += `Last handoff: ${path.basename(info.handoffPath)}\n`;\n } else {\n output += \"No handoff found - context may be lost.\\n\";\n }\n if (verbose) {\n if (info.checkpoint) {\n output += \"\\nCheckpoint JSON:\\n\";\n output += JSON.stringify(info.checkpoint, null, 2) + \"\\n\";\n }\n if (info.handoffContent) {\n output += \"\\nHandoff content:\\n\";\n output += info.handoffContent.trim() + \"\\n\";\n }\n }\n output += \"\\n\" + \"\\u2550\".repeat(40) + \"\\n\";\n output += \"Run `clawvault recap` to see full context.\\n\";\n return output;\n}\n\nexport {\n recover,\n formatRecoveryInfo\n};\n",1112 "inputSchema": {},1113 "outputSchema": null,1114 "icons": null,1115 "annotations": null,1116 "meta": null,1117 "execution": null1118 },1119 {1120 "name": "chunk-4KDZZW4X.js",1121 "title": null,1122 "description": "Script: chunk-4KDZZW4X.js. Code:\n// src/lib/config.ts\nimport * as path from \"path\";\nfunction getVaultPath() {\n const vaultPath = process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n throw new Error(\"CLAWVAULT_PATH environment variable not set\");\n }\n return path.resolve(vaultPath);\n}\n\nexport {\n getVaultPath\n};\n",1123 "inputSchema": {},1124 "outputSchema": null,1125 "icons": null,1126 "annotations": null,1127 "meta": null,1128 "execution": null1129 },1130 {1131 "name": "chunk-AZRV2I5U.js",1132 "title": null,1133 "description": "Script: chunk-AZRV2I5U.js. Code:\n// src/lib/session-utils.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nfunction getOpenClawAgentsDir() {\n return path.join(os.homedir(), \".openclaw\", \"agents\");\n}\nfunction getSessionsDir(agentId) {\n return path.join(getOpenClawAgentsDir(), agentId, \"sessions\");\n}\nfunction getSessionsJsonPath(agentId) {\n return path.join(getSessionsDir(agentId), \"sessions.json\");\n}\nfunction getSessionFilePath(agentId, sessionId) {\n return path.join(getSessionsDir(agentId), `${sessionId}.jsonl`);\n}\nfunction listAgents() {\n const agentsDir = getOpenClawAgentsDir();\n if (!fs.existsSync(agentsDir)) {\n return [];\n }\n return fs.readdirSync(agentsDir).filter((name) => {\n const sessionsDir = getSessionsDir(name);\n return fs.existsSync(sessionsDir) && fs.statSync(sessionsDir).isDirectory();\n });\n}\nfunction loadSessionsStore(agentId) {\n const sessionsJsonPath = getSessionsJsonPath(agentId);\n if (!fs.existsSync(sessionsJsonPath)) {\n return null;\n }\n try {\n const content = fs.readFileSync(sessionsJsonPath, \"utf-8\");\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\nfunction findMainSession(agentId) {\n const store = loadSessionsStore(agentId);\n if (!store) return null;\n const mainKey = `agent:${agentId}:main`;\n const entry = store[mainKey];\n if (entry?.sessionId) {\n const filePath = getSessionFilePath(agentId, entry.sessionId);\n if (fs.existsSync(filePath)) {\n return {\n sessionId: entry.sessionId,\n sessionKey: mainKey,\n agentId,\n filePath,\n updatedAt: entry.updatedAt\n };\n }\n }\n return null;\n}\nfunction findSessionById(agentId, sessionId) {\n const filePath = getSessionFilePath(agentId, sessionId);\n if (!fs.existsSync(filePath)) {\n return null;\n }\n const store = loadSessionsStore(agentId);\n let sessionKey;\n let updatedAt;\n if (store) {\n for (const [key, entry] of Object.entries(store)) {\n if (entry.sessionId === sessionId) {\n sessionKey = key;\n updatedAt = entry.updatedAt;\n break;\n }\n }\n }\n return {\n sessionId,\n sessionKey: sessionKey || `agent:${agentId}:unknown`,\n agentId,\n filePath,\n updatedAt\n };\n}\nfunction listSessions(agentId) {\n const sessionsDir = getSessionsDir(agentId);\n if (!fs.existsSync(sessionsDir)) {\n return [];\n }\n const store = loadSessionsStore(agentId);\n const sessions = [];\n const files = fs.readdirSync(sessionsDir).filter((f) => f.endsWith(\".jsonl\") && !f.includes(\".backup\") && !f.includes(\".deleted\") && !f.includes(\".corrupted\"));\n for (const file of files) {\n const sessionId = file.replace(\".jsonl\", \"\");\n const filePath = path.join(sessionsDir, file);\n let sessionKey = `agent:${agentId}:unknown`;\n let updatedAt;\n if (store) {\n for (const [key, entry] of Object.entries(store)) {\n if (entry.sessionId === sessionId) {\n sessionKey = key;\n updatedAt = entry.updatedAt;\n break;\n }\n }\n }\n sessions.push({\n sessionId,\n sessionKey,\n agentId,\n filePath,\n updatedAt\n });\n }\n return sessions.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n}\nfunction backupSession(filePath) {\n const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, \"\").replace(\"T\", \"-\").slice(0, 15);\n const backupPath = `${filePath}.backup-${timestamp}`;\n fs.copyFileSync(filePath, backupPath);\n return backupPath;\n}\n\nexport {\n getOpenClawAgentsDir,\n getSessionsDir,\n getSessionsJsonPath,\n getSessionFilePath,\n listAgents,\n loadSessionsStore,\n findMainSession,\n findSessionById,\n listSessions,\n backupSession\n};\n",1134 "inputSchema": {},1135 "outputSchema": null,1136 "icons": null,1137 "annotations": null,1138 "meta": null,1139 "execution": null1140 },1141 {1142 "name": "chunk-4VQTUVH7.js",1143 "title": null,1144 "description": "Script: chunk-4VQTUVH7.js. Code:\nimport {\n buildEntityIndex\n} from \"./chunk-J7ZWCI2C.js\";\n\n// src/lib/backlinks.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nvar CLAWVAULT_DIR = \".clawvault\";\nvar BACKLINKS_FILE = \"backlinks.json\";\nvar WIKI_LINK_REGEX = /\\[\\[([^\\]]+)\\]\\]/g;\nfunction ensureClawvaultDir(vaultPath) {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\nfunction toVaultId(vaultPath, filePath) {\n const relative2 = path.relative(vaultPath, filePath).replace(/\\.md$/, \"\");\n return relative2.split(path.sep).join(\"/\");\n}\nfunction normalizeLinkTarget(raw) {\n let target = raw.trim();\n if (!target) return \"\";\n if (target.startsWith(\"[[\") && target.endsWith(\"]]\")) {\n target = target.slice(2, -2);\n }\n const pipeIndex = target.indexOf(\"|\");\n if (pipeIndex !== -1) {\n target = target.slice(0, pipeIndex);\n }\n if (target.startsWith(\"#\")) return \"\";\n const hashIndex = target.indexOf(\"#\");\n if (hashIndex !== -1) {\n target = target.slice(0, hashIndex);\n }\n target = target.trim();\n if (!target) return \"\";\n if (target.endsWith(\".md\")) {\n target = target.slice(0, -3);\n }\n if (target.startsWith(\"/\")) {\n target = target.slice(1);\n }\n return target.replace(/\\\\/g, \"/\");\n}\nfunction listMarkdownFiles(vaultPath) {\n const files = [];\n const skipDirs = /* @__PURE__ */ new Set([\"archive\", \"templates\", \"node_modules\"]);\n function walk(dir) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name.startsWith(\".\") || skipDirs.has(entry.name)) continue;\n walk(fullPath);\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n files.push(fullPath);\n }\n }\n }\n walk(vaultPath);\n return files;\n}\nfunction buildKnownIds(vaultPath, files) {\n const ids = /* @__PURE__ */ new Set();\n const idsLower = /* @__PURE__ */ new Map();\n for (const file of files) {\n const id = toVaultId(vaultPath, file);\n ids.add(id);\n const lower = id.toLowerCase();\n if (!idsLower.has(lower)) {\n idsLower.set(lower, id);\n }\n }\n return { ids, idsLower };\n}\nfunction resolveTarget(target, known, entityIndex) {\n if (!target) return null;\n if (known.ids.has(target)) return target;\n const lower = target.toLowerCase();\n if (known.idsLower.has(lower)) return known.idsLower.get(lower);\n if (entityIndex?.entries.has(lower)) return entityIndex.entries.get(lower);\n return null;\n}\nfunction scanVaultLinks(vaultPath, options = {}) {\n const files = listMarkdownFiles(vaultPath);\n const known = buildKnownIds(vaultPath, files);\n const entityIndex = options.entityIndex ?? buildEntityIndex(vaultPath);\n const backlinks = /* @__PURE__ */ new Map();\n const orphans = [];\n let linkCount = 0;\n for (const file of files) {\n const sourceId = toVaultId(vaultPath, file);\n const content = fs.readFileSync(file, \"utf-8\");\n const matches = content.match(WIKI_LINK_REGEX) || [];\n linkCount += matches.length;\n for (const match of matches) {\n const target = normalizeLinkTarget(match);\n if (!target) continue;\n const resolved = resolveTarget(target, known, entityIndex);\n if (!resolved) {\n orphans.push({ source: sourceId, target });\n continue;\n }\n if (!backlinks.has(resolved)) {\n backlinks.set(resolved, /* @__PURE__ */ new Set());\n }\n backlinks.get(resolved).add(sourceId);\n }\n }\n const backlinksMap = /* @__PURE__ */ new Map();\n for (const [target, sources] of backlinks) {\n backlinksMap.set(target, [...sources].sort());\n }\n return { backlinks: backlinksMap, orphans, linkCount };\n}\nfunction writeBacklinksIndex(vaultPath, backlinks) {\n const dir = ensureClawvaultDir(vaultPath);\n const output = {};\n const targets = [...backlinks.keys()].sort();\n for (const target of targets) {\n const sources = backlinks.get(target) || [];\n output[target] = [...new Set(sources)].sort();\n }\n fs.writeFileSync(path.join(dir, BACKLINKS_FILE), JSON.stringify(output, null, 2));\n}\nfunction readBacklinksIndex(vaultPath) {\n const filePath = path.join(vaultPath, CLAWVAULT_DIR, BACKLINKS_FILE);\n if (!fs.existsSync(filePath)) return null;\n try {\n const raw = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n const map = /* @__PURE__ */ new Map();\n for (const [target, sources] of Object.entries(raw)) {\n if (Array.isArray(sources)) {\n map.set(target, sources);\n }\n }\n return map;\n } catch {\n return null;\n }\n}\nfunction rebuildBacklinksIndex(vaultPath, options = {}) {\n const result = scanVaultLinks(vaultPath, options);\n writeBacklinksIndex(vaultPath, result.backlinks);\n return result;\n}\n\nexport {\n scanVaultLinks,\n readBacklinksIndex,\n rebuildBacklinksIndex\n};\n",1145 "inputSchema": {},1146 "outputSchema": null,1147 "icons": null,1148 "annotations": null,1149 "meta": null,1150 "execution": null1151 },1152 {1153 "name": "chunk-J7ZWCI2C.js",1154 "title": null,1155 "description": "Script: chunk-J7ZWCI2C.js. Code:\n// src/lib/entity-index.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport matter from \"gray-matter\";\nfunction buildEntityIndex(vaultPath) {\n const entries = /* @__PURE__ */ new Map();\n const byPath = /* @__PURE__ */ new Map();\n const entityFolders = [\"people\", \"projects\", \"agents\", \"lessons\", \"decisions\", \"commitments\"];\n for (const folder of entityFolders) {\n const folderPath = path.join(vaultPath, folder);\n if (!fs.existsSync(folderPath)) continue;\n const files = fs.readdirSync(folderPath).filter((f) => f.endsWith(\".md\"));\n for (const file of files) {\n const filePath = path.join(folderPath, file);\n const content = fs.readFileSync(filePath, \"utf-8\");\n const { data: frontmatter } = matter(content);\n const relativePath = `${folder}/${file.replace(\".md\", \"\")}`;\n const baseName = file.replace(\".md\", \"\");\n const aliases = [baseName];\n if (frontmatter.title && frontmatter.title.toLowerCase() !== baseName.toLowerCase()) {\n aliases.push(frontmatter.title);\n }\n if (Array.isArray(frontmatter.aliases)) {\n aliases.push(...frontmatter.aliases);\n }\n for (const alias of aliases) {\n const key = alias.toLowerCase();\n if (!entries.has(key)) {\n entries.set(key, relativePath);\n }\n }\n byPath.set(relativePath, { path: relativePath, aliases });\n }\n }\n return { entries, byPath };\n}\nfunction getSortedAliases(index) {\n const result = [];\n for (const [alias, path2] of index.entries) {\n result.push({ alias, path: path2 });\n }\n result.sort((a, b) => b.alias.length - a.alias.length);\n return result;\n}\n\nexport {\n buildEntityIndex,\n getSortedAliases\n};\n",1156 "inputSchema": {},1157 "outputSchema": null,1158 "icons": null,1159 "annotations": null,1160 "meta": null,1161 "execution": null1162 },1163 {1164 "name": "types-DO8rJ490.d.ts",1165 "title": null,1166 "description": "Script: types-DO8rJ490.d.ts. Code:\n/**\n * ClawVault Types - The elephant's memory structure\n */\ninterface VaultConfig {\n /** Root path of the vault */\n path: string;\n /** Name of the vault */\n name: string;\n /** Categories to create on init */\n categories: string[];\n /** qmd collection name (defaults to vault name if not set) */\n qmdCollection?: string;\n /** Root path for qmd collection (defaults to vault path) */\n qmdRoot?: string;\n /** Custom templates path (optional) */\n templatesPath?: string;\n}\ninterface VaultMeta {\n name: string;\n version: string;\n created: string;\n lastUpdated: string;\n categories: string[];\n documentCount: number;\n /** qmd collection name (defaults to vault name if not set) */\n qmdCollection?: string;\n /** Root path for qmd collection (defaults to vault path) */\n qmdRoot?: string;\n}\ninterface Document {\n /** Unique ID (relative path without extension) */\n id: string;\n /** Full file path */\n path: string;\n /** Category (folder name) */\n category: string;\n /** Document title */\n title: string;\n /** Raw content */\n content: string;\n /** Frontmatter metadata */\n frontmatter: Record<string, unknown>;\n /** Extracted wiki-links [[like-this]] */\n links: string[];\n /** Tags extracted from content */\n tags: string[];\n /** Last modified timestamp */\n modified: Date;\n}\ninterface SearchResult {\n /** Document that matched */\n document: Document;\n /** Relevance score (0-1) */\n score: number;\n /** Matching snippet */\n snippet: string;\n /** Which terms matched */\n matchedTerms: string[];\n}\ninterface SearchOptions {\n /** Max results to return */\n limit?: number;\n /** Minimum score threshold (0-1) */\n minScore?: number;\n /** Filter by category */\n category?: string;\n /** Filter by tags */\n tags?: string[];\n /** Include full content in results */\n fullContent?: boolean;\n}\ninterface StoreOptions {\n /** Category to store in */\n category: string;\n /** Document title (used for filename) */\n title: string;\n /** Content body */\n content: string;\n /** Frontmatter metadata */\n frontmatter?: Record<string, unknown>;\n /** Override existing file */\n overwrite?: boolean;\n /** Trigger qmd update after storing */\n qmdUpdate?: boolean;\n /** Trigger qmd embed after storing (implies qmdUpdate) */\n qmdEmbed?: boolean;\n}\ninterface SyncOptions {\n /** Target directory to sync to */\n target: string;\n /** Delete files in target not in source */\n deleteOrphans?: boolean;\n /** Dry run - don't actually sync */\n dryRun?: boolean;\n}\ninterface SyncResult {\n copied: string[];\n deleted: string[];\n unchanged: string[];\n errors: string[];\n}\ntype Category = 'preferences' | 'decisions' | 'patterns' | 'people' | 'projects' | 'goals' | 'transcripts' | 'inbox' | 'templates' | 'facts' | 'feelings' | 'lessons' | 'commitments' | 'handoffs' | string;\ndeclare const DEFAULT_CATEGORIES: Category[];\n/**\n * Memory Type Taxonomy (Benthic's 8 categories)\n * Knowing WHAT KIND of thing helps you know WHERE to put it\n */\ntype MemoryType = 'fact' | 'feeling' | 'decision' | 'lesson' | 'commitment' | 'preference' | 'relationship' | 'project';\ndeclare const MEMORY_TYPES: MemoryType[];\n/**\n * Memory type to category mapping\n */\ndeclare const TYPE_TO_CATEGORY: Record<MemoryType, Category>;\n/**\n * Handoff document - bridges sessions\n */\ninterface HandoffDocument {\n /** When this handoff was created */\n created: string;\n /** Session key or identifier */\n sessionKey?: string;\n /** What I was working on */\n workingOn: string[];\n /** What is currently blocked */\n blocked: string[];\n /** What comes next */\n nextSteps: string[];\n /** Emotional state/energy */\n feeling?: string;\n /** Key decisions made */\n decisions?: string[];\n /** Open questions */\n openQuestions?: string[];\n}\n/**\n * Session recap - who I was when I woke up\n */\ninterface SessionRecap {\n /** When recap was generated */\n generated: string;\n /** Recent handoffs (last N) */\n recentHandoffs: HandoffDocument[];\n /** Active projects */\n activeProjects: string[];\n /** Pending commitments */\n pendingCommitments: string[];\n /** Recent decisions made */\n recentDecisions?: string[];\n /** Recent lessons learned */\n recentLessons: string[];\n /** Key relationships to remember */\n keyRelationships: string[];\n /** Current emotional arc */\n emotionalArc?: string;\n}\ndeclare const DEFAULT_CONFIG: Partial<VaultConfig>;\n\nexport { type Category as C, type Document as D, type HandoffDocument as H, type MemoryType as M, type StoreOptions as S, TYPE_TO_CATEGORY as T, type VaultConfig as V, type SearchOptions as a, type SearchResult as b, type SyncOptions as c, type SyncResult as d, type SessionRecap as e, DEFAULT_CATEGORIES as f, DEFAULT_CONFIG as g, MEMORY_TYPES as h, type VaultMeta as i };\n",1167 "inputSchema": {},1168 "outputSchema": null,1169 "icons": null,1170 "annotations": null,1171 "meta": null,1172 "execution": null1173 },1174 {1175 "name": "index.js",1176 "title": null,1177 "description": "Script: index.js. Code:\nimport {\n buildTemplateVariables,\n renderTemplate\n} from \"./chunk-7766SIJP.js\";\nimport {\n ClawVault,\n createVault,\n findVault\n} from \"./chunk-MXNXWOPL.js\";\nimport {\n setupCommand\n} from \"./chunk-QYJI73KF.js\";\nimport {\n DEFAULT_CATEGORIES,\n DEFAULT_CONFIG,\n MEMORY_TYPES,\n QMD_INSTALL_COMMAND,\n QMD_INSTALL_URL,\n QmdUnavailableError,\n SearchEngine,\n TYPE_TO_CATEGORY,\n extractTags,\n extractWikiLinks,\n hasQmd,\n qmdEmbed,\n qmdUpdate\n} from \"./chunk-VJIFT5T5.js\";\n\n// src/index.ts\nimport * as fs from \"fs\";\nfunction readPackageVersion() {\n try {\n const pkgUrl = new URL(\"../package.json\", import.meta.url);\n const pkg = JSON.parse(fs.readFileSync(pkgUrl, \"utf-8\"));\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\nvar VERSION = readPackageVersion();\nexport {\n ClawVault,\n DEFAULT_CATEGORIES,\n DEFAULT_CONFIG,\n MEMORY_TYPES,\n QMD_INSTALL_COMMAND,\n QMD_INSTALL_URL,\n QmdUnavailableError,\n SearchEngine,\n TYPE_TO_CATEGORY,\n VERSION,\n buildTemplateVariables,\n createVault,\n extractTags,\n extractWikiLinks,\n findVault,\n hasQmd,\n qmdEmbed,\n qmdUpdate,\n renderTemplate,\n setupCommand\n};\n",1178 "inputSchema": {},1179 "outputSchema": null,1180 "icons": null,1181 "annotations": null,1182 "meta": null,1183 "execution": null1184 },1185 {1186 "name": "chunk-VJIFT5T5.js",1187 "title": null,1188 "description": "Script: chunk-VJIFT5T5.js. Code:\n// src/types.ts\nvar DEFAULT_CATEGORIES = [\n \"preferences\",\n \"decisions\",\n \"patterns\",\n \"people\",\n \"projects\",\n \"goals\",\n \"transcripts\",\n \"inbox\",\n \"templates\"\n];\nvar MEMORY_TYPES = [\n \"fact\",\n \"feeling\",\n \"decision\",\n \"lesson\",\n \"commitment\",\n \"preference\",\n \"relationship\",\n \"project\"\n];\nvar TYPE_TO_CATEGORY = {\n fact: \"facts\",\n feeling: \"feelings\",\n decision: \"decisions\",\n lesson: \"lessons\",\n commitment: \"commitments\",\n preference: \"preferences\",\n relationship: \"people\",\n project: \"projects\"\n};\nvar DEFAULT_CONFIG = {\n categories: DEFAULT_CATEGORIES\n};\n\n// src/lib/search.ts\nimport { execFileSync, spawnSync } from \"child_process\";\nimport * as path from \"path\";\nvar QMD_INSTALL_URL = \"https://github.com/tobi/qmd\";\nvar QMD_INSTALL_COMMAND = \"bun install -g github:tobi/qmd\";\nvar QMD_NOT_INSTALLED_MESSAGE = `ClawVault requires qmd. Install: ${QMD_INSTALL_COMMAND}`;\nvar QmdUnavailableError = class extends Error {\n constructor(message = QMD_NOT_INSTALLED_MESSAGE) {\n super(message);\n this.name = \"QmdUnavailableError\";\n }\n};\nfunction ensureJsonArgs(args) {\n return args.includes(\"--json\") ? args : [...args, \"--json\"];\n}\nfunction tryParseJson(raw) {\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\nfunction extractJsonPayload(raw) {\n const start = raw.search(/[\\[{]/);\n if (start === -1) return null;\n const end = Math.max(raw.lastIndexOf(\"]\"), raw.lastIndexOf(\"}\"));\n if (end <= start) return null;\n return raw.slice(start, end + 1);\n}\nfunction parseQmdOutput(raw) {\n const trimmed = raw.trim();\n if (!trimmed) return [];\n const direct = tryParseJson(trimmed);\n const extracted = direct ? null : extractJsonPayload(trimmed);\n const parsed = direct ?? (extracted ? tryParseJson(extracted) : null);\n if (!parsed) {\n throw new Error(\"qmd returned non-JSON output. Ensure qmd supports --json.\");\n }\n if (Array.isArray(parsed)) {\n return parsed;\n }\n if (parsed && typeof parsed === \"object\") {\n const candidate = parsed.results ?? parsed.items ?? parsed.data;\n if (Array.isArray(candidate)) {\n return candidate;\n }\n }\n throw new Error(\"qmd returned an unexpected JSON shape.\");\n}\nfunction ensureQmdAvailable() {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n}\nfunction execQmd(args) {\n ensureQmdAvailable();\n const finalArgs = ensureJsonArgs(args);\n try {\n const result = execFileSync(\"qmd\", finalArgs, {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n maxBuffer: 10 * 1024 * 1024\n // 10MB\n });\n return parseQmdOutput(result);\n } catch (err) {\n if (err?.code === \"ENOENT\") {\n throw new QmdUnavailableError();\n }\n const output = [err?.stdout, err?.stderr].filter(Boolean).join(\"\\n\");\n if (output) {\n try {\n return parseQmdOutput(output);\n } catch {\n }\n }\n const message = err?.message ? `qmd failed: ${err.message}` : \"qmd failed\";\n throw new Error(message);\n }\n}\nfunction hasQmd() {\n const result = spawnSync(\"qmd\", [\"--version\"], { stdio: \"ignore\" });\n return !result.error;\n}\nfunction qmdUpdate(collection) {\n ensureQmdAvailable();\n const args = [\"update\"];\n if (collection) {\n args.push(\"-c\", collection);\n }\n execFileSync(\"qmd\", args, { stdio: \"inherit\" });\n}\nfunction qmdEmbed(collection) {\n ensureQmdAvailable();\n const args = [\"embed\"];\n if (collection) {\n args.push(\"-c\", collection);\n }\n execFileSync(\"qmd\", args, { stdio: \"inherit\" });\n}\nvar SearchEngine = class {\n documents = /* @__PURE__ */ new Map();\n collection = \"clawvault\";\n vaultPath = \"\";\n collectionRoot = \"\";\n /**\n * Set the collection name (usually vault name)\n */\n setCollection(name) {\n this.collection = name;\n }\n /**\n * Set the vault path for file resolution\n */\n setVaultPath(vaultPath) {\n this.vaultPath = vaultPath;\n }\n /**\n * Set the collection root for qmd:// URI resolution\n */\n setCollectionRoot(root) {\n this.collectionRoot = path.resolve(root);\n }\n /**\n * Add or update a document in the local cache\n * Note: qmd indexing happens via qmd update command\n */\n addDocument(doc) {\n this.documents.set(doc.id, doc);\n }\n /**\n * Remove a document from the local cache\n */\n removeDocument(id) {\n this.documents.delete(id);\n }\n /**\n * No-op for qmd - indexing is managed externally\n */\n rebuildIDF() {\n }\n /**\n * BM25 search via qmd\n */\n search(query, options = {}) {\n return this.runQmdQuery(\"search\", query, options);\n }\n /**\n * Vector/semantic search via qmd vsearch\n */\n vsearch(query, options = {}) {\n return this.runQmdQuery(\"vsearch\", query, options);\n }\n /**\n * Combined search with query expansion (qmd query command)\n */\n query(query, options = {}) {\n return this.runQmdQuery(\"query\", query, options);\n }\n runQmdQuery(command, query, options) {\n const {\n limit = 10,\n minScore = 0,\n category,\n tags,\n fullContent = false\n } = options;\n if (!query.trim()) return [];\n const args = [\n command,\n query,\n \"-n\",\n String(limit * 2),\n \"--json\"\n ];\n if (this.collection) {\n args.push(\"-c\", this.collection);\n }\n const qmdResults = execQmd(args);\n return this.convertResults(qmdResults, {\n limit,\n minScore,\n category,\n tags,\n fullContent\n });\n }\n /**\n * Convert qmd results to ClawVault SearchResult format\n */\n convertResults(qmdResults, options) {\n const { limit = 10, minScore = 0, category, tags, fullContent = false } = options;\n const results = [];\n const maxScore = qmdResults[0]?.score || 1;\n for (const qr of qmdResults) {\n const filePath = this.qmdUriToPath(qr.file);\n const relativePath = this.vaultPath ? path.relative(this.vaultPath, filePath) : filePath;\n const docId = relativePath.replace(/\\.md$/, \"\");\n let doc = this.documents.get(docId);\n const parts = relativePath.split(path.sep);\n const docCategory = parts.length > 1 ? parts[0] : \"root\";\n if (category && docCategory !== category) continue;\n if (tags && tags.length > 0 && doc) {\n const docTags = new Set(doc.tags);\n if (!tags.some((t) => docTags.has(t))) continue;\n }\n const normalizedScore = maxScore > 0 ? qr.score / maxScore : 0;\n if (normalizedScore < minScore) continue;\n if (!doc) {\n doc = {\n id: docId,\n path: filePath,\n category: docCategory,\n title: qr.title || path.basename(relativePath, \".md\"),\n content: \"\",\n // Content loaded separately if needed\n frontmatter: {},\n links: [],\n tags: [],\n modified: /* @__PURE__ */ new Date()\n };\n }\n results.push({\n document: fullContent ? doc : { ...doc, content: \"\" },\n score: normalizedScore,\n snippet: this.cleanSnippet(qr.snippet),\n matchedTerms: []\n // qmd doesn't provide this\n });\n if (results.length >= limit) break;\n }\n return results;\n }\n /**\n * Convert qmd:// URI to file path\n */\n qmdUriToPath(uri) {\n if (uri.startsWith(\"qmd://\")) {\n const withoutScheme = uri.slice(6);\n const slashIndex = withoutScheme.indexOf(\"/\");\n if (slashIndex > -1) {\n const relativePath = withoutScheme.slice(slashIndex + 1);\n const root = this.collectionRoot || this.vaultPath;\n if (root) {\n return path.join(root, relativePath);\n }\n return relativePath;\n }\n }\n return uri;\n }\n /**\n * Clean up qmd snippet format\n */\n cleanSnippet(snippet) {\n if (!snippet) return \"\";\n return snippet.replace(/@@ [-+]?\\d+,?\\d* @@ \\([^)]+\\)/g, \"\").trim().split(\"\\n\").slice(0, 3).join(\"\\n\").slice(0, 300);\n }\n /**\n * Get all cached documents\n */\n getAllDocuments() {\n return [...this.documents.values()];\n }\n /**\n * Get document count\n */\n get size() {\n return this.documents.size;\n }\n /**\n * Clear the local document cache\n */\n clear() {\n this.documents.clear();\n }\n /**\n * Export documents for persistence\n */\n export() {\n return {\n documents: [...this.documents.values()]\n };\n }\n /**\n * Import from persisted data\n */\n import(data) {\n this.clear();\n for (const doc of data.documents) {\n this.addDocument(doc);\n }\n }\n};\nfunction extractWikiLinks(content) {\n const matches = content.match(/\\[\\[([^\\]]+)\\]\\]/g) || [];\n return matches.map((m) => m.slice(2, -2).toLowerCase());\n}\nfunction extractTags(content) {\n const matches = content.match(/#[\\w-]+/g) || [];\n return [...new Set(matches.map((m) => m.slice(1).toLowerCase()))];\n}\n\nexport {\n DEFAULT_CATEGORIES,\n MEMORY_TYPES,\n TYPE_TO_CATEGORY,\n DEFAULT_CONFIG,\n QMD_INSTALL_URL,\n QMD_INSTALL_COMMAND,\n QmdUnavailableError,\n hasQmd,\n qmdUpdate,\n qmdEmbed,\n SearchEngine,\n extractWikiLinks,\n extractTags\n};\n",1189 "inputSchema": {},1190 "outputSchema": null,1191 "icons": null,1192 "annotations": null,1193 "meta": null,1194 "execution": null1195 }1196 ]1197 },1198 "error": null1199 }1200 ],1201 "issues": [1202 {1203 "code": "W004",1204 "message": "The MCP server is not in our registry.",1205 "reference": [1206 0,1207 null1208 ],1209 "extra_data": null1210 }1211 ],1212 "labels": [1213 [1214 {1215 "is_public_sink": 0,1216 "destructive": 0,1217 "untrusted_content": 0,1218 "private_data": 01219 },1220 {1221 "is_public_sink": 0,1222 "destructive": 0,1223 "untrusted_content": 0,1224 "private_data": 01225 },1226 {1227 "is_public_sink": 0,1228 "destructive": 0,1229 "untrusted_content": 0,1230 "private_data": 01231 },1232 {1233 "is_public_sink": 0,1234 "destructive": 0,1235 "untrusted_content": 0,1236 "private_data": 01237 },1238 {1239 "is_public_sink": 0,1240 "destructive": 0,1241 "untrusted_content": 0,1242 "private_data": 01243 },1244 {1245 "is_public_sink": 0,1246 "destructive": 0,1247 "untrusted_content": 0,1248 "private_data": 01249 },1250 {1251 "is_public_sink": 0,1252 "destructive": 0,1253 "untrusted_content": 0,1254 "private_data": 01255 },1256 {1257 "is_public_sink": 0,1258 "destructive": 0,1259 "untrusted_content": 0,1260 "private_data": 01261 },1262 {1263 "is_public_sink": 0,1264 "destructive": 0,1265 "untrusted_content": 0,1266 "private_data": 01267 },1268 {1269 "is_public_sink": 0,1270 "destructive": 0,1271 "untrusted_content": 0,1272 "private_data": 01273 },1274 {1275 "is_public_sink": 0,1276 "destructive": 0,1277 "untrusted_content": 0,1278 "private_data": 01279 },1280 {1281 "is_public_sink": 0,1282 "destructive": 0,1283 "untrusted_content": 0,1284 "private_data": 01285 },1286 {1287 "is_public_sink": 0,1288 "destructive": 0,1289 "untrusted_content": 0,1290 "private_data": 01291 },1292 {1293 "is_public_sink": 0,1294 "destructive": 0,1295 "untrusted_content": 0,1296 "private_data": 01297 },1298 {1299 "is_public_sink": 0,1300 "destructive": 0,1301 "untrusted_content": 0,1302 "private_data": 01303 },1304 {1305 "is_public_sink": 0,1306 "destructive": 0,1307 "untrusted_content": 0,1308 "private_data": 01309 },1310 {1311 "is_public_sink": 0,1312 "destructive": 0,1313 "untrusted_content": 0,1314 "private_data": 01315 },1316 {1317 "is_public_sink": 0,1318 "destructive": 0,1319 "untrusted_content": 0,1320 "private_data": 01321 },1322 {1323 "is_public_sink": 0,1324 "destructive": 0,1325 "untrusted_content": 0,1326 "private_data": 01327 },1328 {1329 "is_public_sink": 0,1330 "destructive": 0,1331 "untrusted_content": 0,1332 "private_data": 01333 },1334 {1335 "is_public_sink": 0,1336 "destructive": 0,1337 "untrusted_content": 0,1338 "private_data": 01339 },1340 {1341 "is_public_sink": 0,1342 "destructive": 0,1343 "untrusted_content": 0,1344 "private_data": 01345 },1346 {1347 "is_public_sink": 0,1348 "destructive": 0,1349 "untrusted_content": 0,1350 "private_data": 01351 },1352 {1353 "is_public_sink": 0,1354 "destructive": 0,1355 "untrusted_content": 0,1356 "private_data": 01357 },1358 {1359 "is_public_sink": 0,1360 "destructive": 0,1361 "untrusted_content": 0,1362 "private_data": 01363 },1364 {1365 "is_public_sink": 0,1366 "destructive": 0,1367 "untrusted_content": 0,1368 "private_data": 01369 },1370 {1371 "is_public_sink": 0,1372 "destructive": 0,1373 "untrusted_content": 0,1374 "private_data": 01375 },1376 {1377 "is_public_sink": 0,1378 "destructive": 0,1379 "untrusted_content": 0,1380 "private_data": 01381 },1382 {1383 "is_public_sink": 0,1384 "destructive": 0,1385 "untrusted_content": 0,1386 "private_data": 01387 },1388 {1389 "is_public_sink": 0,1390 "destructive": 0,1391 "untrusted_content": 0,1392 "private_data": 01393 },1394 {1395 "is_public_sink": 0,1396 "destructive": 0,1397 "untrusted_content": 0,1398 "private_data": 01399 },1400 {1401 "is_public_sink": 0,1402 "destructive": 0,1403 "untrusted_content": 0,1404 "private_data": 01405 },1406 {1407 "is_public_sink": 0,1408 "destructive": 0,1409 "untrusted_content": 0,1410 "private_data": 01411 },1412 {1413 "is_public_sink": 0,1414 "destructive": 0,1415 "untrusted_content": 0,1416 "private_data": 01417 },1418 {1419 "is_public_sink": 0,1420 "destructive": 0,1421 "untrusted_content": 0,1422 "private_data": 01423 },1424 {1425 "is_public_sink": 0,1426 "destructive": 0,1427 "untrusted_content": 0,1428 "private_data": 01429 },1430 {1431 "is_public_sink": 0,1432 "destructive": 0,1433 "untrusted_content": 0,1434 "private_data": 01435 },1436 {1437 "is_public_sink": 0,1438 "destructive": 0,1439 "untrusted_content": 0,1440 "private_data": 01441 },1442 {1443 "is_public_sink": 0,1444 "destructive": 0,1445 "untrusted_content": 0,1446 "private_data": 01447 },1448 {1449 "is_public_sink": 0,1450 "destructive": 0,1451 "untrusted_content": 0,1452 "private_data": 01453 },1454 {1455 "is_public_sink": 0,1456 "destructive": 0,1457 "untrusted_content": 0,1458 "private_data": 01459 },1460 {1461 "is_public_sink": 0,1462 "destructive": 0,1463 "untrusted_content": 0,1464 "private_data": 01465 },1466 {1467 "is_public_sink": 0,1468 "destructive": 0,1469 "untrusted_content": 0,1470 "private_data": 01471 },1472 {1473 "is_public_sink": 0,1474 "destructive": 0,1475 "untrusted_content": 0,1476 "private_data": 01477 },1478 {1479 "is_public_sink": 0,1480 "destructive": 0,1481 "untrusted_content": 0,1482 "private_data": 01483 },1484 {1485 "is_public_sink": 0,1486 "destructive": 0,1487 "untrusted_content": 0,1488 "private_data": 01489 },1490 {1491 "is_public_sink": 0,1492 "destructive": 0,1493 "untrusted_content": 0,1494 "private_data": 01495 },1496 {1497 "is_public_sink": 0,1498 "destructive": 0,1499 "untrusted_content": 0,1500 "private_data": 01501 },1502 {1503 "is_public_sink": 0,1504 "destructive": 0,1505 "untrusted_content": 0,1506 "private_data": 01507 },1508 {1509 "is_public_sink": 0,1510 "destructive": 0,1511 "untrusted_content": 0,1512 "private_data": 01513 },1514 {1515 "is_public_sink": 0,1516 "destructive": 0,1517 "untrusted_content": 0,1518 "private_data": 01519 },1520 {1521 "is_public_sink": 0,1522 "destructive": 0,1523 "untrusted_content": 0,1524 "private_data": 01525 },1526 {1527 "is_public_sink": 0,1528 "destructive": 0,1529 "untrusted_content": 0,1530 "private_data": 01531 },1532 {1533 "is_public_sink": 0,1534 "destructive": 0,1535 "untrusted_content": 0,1536 "private_data": 01537 },1538 {1539 "is_public_sink": 0,1540 "destructive": 0,1541 "untrusted_content": 0,1542 "private_data": 01543 },1544 {1545 "is_public_sink": 0,1546 "destructive": 0,1547 "untrusted_content": 0,1548 "private_data": 01549 },1550 {1551 "is_public_sink": 0,1552 "destructive": 0,1553 "untrusted_content": 0,1554 "private_data": 01555 },1556 {1557 "is_public_sink": 0,1558 "destructive": 0,1559 "untrusted_content": 0,1560 "private_data": 01561 },1562 {1563 "is_public_sink": 0,1564 "destructive": 0,1565 "untrusted_content": 0,1566 "private_data": 01567 },1568 {1569 "is_public_sink": 0,1570 "destructive": 0,1571 "untrusted_content": 0,1572 "private_data": 01573 },1574 {1575 "is_public_sink": 0,1576 "destructive": 0,1577 "untrusted_content": 0,1578 "private_data": 01579 },1580 {1581 "is_public_sink": 0,1582 "destructive": 0,1583 "untrusted_content": 0,1584 "private_data": 01585 },1586 {1587 "is_public_sink": 0,1588 "destructive": 0,1589 "untrusted_content": 0,1590 "private_data": 01591 },1592 {1593 "is_public_sink": 0,1594 "destructive": 0,1595 "untrusted_content": 0,1596 "private_data": 01597 },1598 {1599 "is_public_sink": 0,1600 "destructive": 0,1601 "untrusted_content": 0,1602 "private_data": 01603 },1604 {1605 "is_public_sink": 0,1606 "destructive": 0,1607 "untrusted_content": 0,1608 "private_data": 01609 },1610 {1611 "is_public_sink": 0,1612 "destructive": 0,1613 "untrusted_content": 0,1614 "private_data": 01615 },1616 {1617 "is_public_sink": 0,1618 "destructive": 0,1619 "untrusted_content": 0,1620 "private_data": 01621 },1622 {1623 "is_public_sink": 0,1624 "destructive": 0,1625 "untrusted_content": 0,1626 "private_data": 01627 },1628 {1629 "is_public_sink": 0,1630 "destructive": 0,1631 "untrusted_content": 0,1632 "private_data": 01633 },1634 {1635 "is_public_sink": 0,1636 "destructive": 0,1637 "untrusted_content": 0,1638 "private_data": 01639 },1640 {1641 "is_public_sink": 0,1642 "destructive": 0,1643 "untrusted_content": 0,1644 "private_data": 01645 },1646 {1647 "is_public_sink": 0,1648 "destructive": 0,1649 "untrusted_content": 0,1650 "private_data": 01651 },1652 {1653 "is_public_sink": 0,1654 "destructive": 0,1655 "untrusted_content": 0,1656 "private_data": 01657 },1658 {1659 "is_public_sink": 0,1660 "destructive": 0,1661 "untrusted_content": 0,1662 "private_data": 01663 },1664 {1665 "is_public_sink": 0,1666 "destructive": 0,1667 "untrusted_content": 0,1668 "private_data": 01669 },1670 {1671 "is_public_sink": 0,1672 "destructive": 0,1673 "untrusted_content": 0,1674 "private_data": 01675 },1676 {1677 "is_public_sink": 0,1678 "destructive": 0,1679 "untrusted_content": 0,1680 "private_data": 01681 },1682 {1683 "is_public_sink": 0,1684 "destructive": 0,1685 "untrusted_content": 0,1686 "private_data": 01687 },1688 {1689 "is_public_sink": 0,1690 "destructive": 0,1691 "untrusted_content": 0,1692 "private_data": 01693 },1694 {1695 "is_public_sink": 0,1696 "destructive": 0,1697 "untrusted_content": 0,1698 "private_data": 01699 },1700 {1701 "is_public_sink": 0,1702 "destructive": 0,1703 "untrusted_content": 0,1704 "private_data": 01705 },1706 {1707 "is_public_sink": 0,1708 "destructive": 0,1709 "untrusted_content": 0,1710 "private_data": 01711 },1712 {1713 "is_public_sink": 0,1714 "destructive": 0,1715 "untrusted_content": 0,1716 "private_data": 01717 },1718 {1719 "is_public_sink": 0,1720 "destructive": 0,1721 "untrusted_content": 0,1722 "private_data": 01723 },1724 {1725 "is_public_sink": 0,1726 "destructive": 0,1727 "untrusted_content": 0,1728 "private_data": 01729 },1730 {1731 "is_public_sink": 0,1732 "destructive": 0,1733 "untrusted_content": 0,1734 "private_data": 01735 },1736 {1737 "is_public_sink": 0,1738 "destructive": 0,1739 "untrusted_content": 0,1740 "private_data": 01741 },1742 {1743 "is_public_sink": 0,1744 "destructive": 0,1745 "untrusted_content": 0,1746 "private_data": 01747 },1748 {1749 "is_public_sink": 0,1750 "destructive": 0,1751 "untrusted_content": 0,1752 "private_data": 01753 },1754 {1755 "is_public_sink": 0,1756 "destructive": 0,1757 "untrusted_content": 0,1758 "private_data": 01759 },1760 {1761 "is_public_sink": 0,1762 "destructive": 0,1763 "untrusted_content": 0,1764 "private_data": 01765 },1766 {1767 "is_public_sink": 0,1768 "destructive": 0,1769 "untrusted_content": 0,1770 "private_data": 01771 },1772 {1773 "is_public_sink": 0,1774 "destructive": 0,1775 "untrusted_content": 0,1776 "private_data": 01777 },1778 {1779 "is_public_sink": 0,1780 "destructive": 0,1781 "untrusted_content": 0,1782 "private_data": 01783 },1784 {1785 "is_public_sink": 0,1786 "destructive": 0,1787 "untrusted_content": 0,1788 "private_data": 01789 },1790 {1791 "is_public_sink": 0,1792 "destructive": 0,1793 "untrusted_content": 0,1794 "private_data": 01795 },1796 {1797 "is_public_sink": 0,1798 "destructive": 0,1799 "untrusted_content": 0,1800 "private_data": 01801 },1802 {1803 "is_public_sink": 0,1804 "destructive": 0,1805 "untrusted_content": 0,1806 "private_data": 01807 },1808 {1809 "is_public_sink": 0,1810 "destructive": 0,1811 "untrusted_content": 0,1812 "private_data": 01813 },1814 {1815 "is_public_sink": 0,1816 "destructive": 0,1817 "untrusted_content": 0,1818 "private_data": 01819 },1820 {1821 "is_public_sink": 0,1822 "destructive": 0,1823 "untrusted_content": 0,1824 "private_data": 01825 },1826 {1827 "is_public_sink": 0,1828 "destructive": 0,1829 "untrusted_content": 0,1830 "private_data": 01831 },1832 {1833 "is_public_sink": 0,1834 "destructive": 0,1835 "untrusted_content": 0,1836 "private_data": 01837 },1838 {1839 "is_public_sink": 0,1840 "destructive": 0,1841 "untrusted_content": 0,1842 "private_data": 01843 },1844 {1845 "is_public_sink": 0,1846 "destructive": 0,1847 "untrusted_content": 0,1848 "private_data": 01849 },1850 {1851 "is_public_sink": 0,1852 "destructive": 0,1853 "untrusted_content": 0,1854 "private_data": 01855 },1856 {1857 "is_public_sink": 0,1858 "destructive": 0,1859 "untrusted_content": 0,1860 "private_data": 01861 }1862 ]1863 ],1864 "error": null1865 }1866}18671868Process exited with code 01869✓ Completed in 165276ms
npm-audit▸11 findings164768ms
View logs
1[2026-02-13T00:36:44.886Z] $ npm audit --json --prefix /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-12{3 "auditReportVersion": 2,4 "vulnerabilities": {5 "@modelcontextprotocol/sdk": {6 "name": "@modelcontextprotocol/sdk",7 "severity": "high",8 "isDirect": false,9 "via": [10 {11 "source": 1113080,12 "name": "@modelcontextprotocol/sdk",13 "dependency": "@modelcontextprotocol/sdk",14 "title": "@modelcontextprotocol/sdk has cross-client data leak via shared server/transport instance reuse",15 "url": "https://github.com/advisories/GHSA-345p-7cg4-v4c7",16 "severity": "high",17 "cwe": [18 "CWE-362"19 ],20 "cvss": {21 "score": 7.1,22 "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N"23 },24 "range": ">=1.10.0 <=1.25.3"25 }26 ],27 "effects": [],28 "range": "1.10.0 - 1.25.3",29 "nodes": [30 "node_modules/@modelcontextprotocol/sdk"31 ],32 "fixAvailable": true33 },34 "axios": {35 "name": "axios",36 "severity": "high",37 "isDirect": false,38 "via": [39 {40 "source": 1113092,41 "name": "axios",42 "dependency": "axios",43 "title": "Axios is Vulnerable to Denial of Service via __proto__ Key in mergeConfig",44 "url": "https://github.com/advisories/GHSA-43fc-jf86-j433",45 "severity": "high",46 "cwe": [47 "CWE-754"48 ],49 "cvss": {50 "score": 7.5,51 "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"52 },53 "range": "<=1.13.4"54 }55 ],56 "effects": [],57 "range": "<=1.13.4",58 "nodes": [59 "node_modules/axios"60 ],61 "fixAvailable": true62 },63 "cmake-js": {64 "name": "cmake-js",65 "severity": "high",66 "isDirect": false,67 "via": [68 "tar"69 ],70 "effects": [71 "node-llama-cpp"72 ],73 "range": "<=7.4.0",74 "nodes": [75 "node_modules/cmake-js"76 ],77 "fixAvailable": true78 },79 "esbuild": {80 "name": "esbuild",81 "severity": "moderate",82 "isDirect": false,83 "via": [84 {85 "source": 1102341,86 "name": "esbuild",87 "dependency": "esbuild",88 "title": "esbuild enables any website to send any requests to the development server and read the response",89 "url": "https://github.com/advisories/GHSA-67mh-4wv8-2f99",90 "severity": "moderate",91 "cwe": [92 "CWE-346"93 ],94 "cvss": {95 "score": 5.3,96 "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N"97 },98 "range": "<=0.24.2"99 }100 ],101 "effects": [102 "vite"103 ],104 "range": "<=0.24.2",105 "nodes": [106 "node_modules/vite/node_modules/esbuild"107 ],108 "fixAvailable": {109 "name": "vitest",110 "version": "4.0.18",111 "isSemVerMajor": true112 }113 },114 "node-llama-cpp": {115 "name": "node-llama-cpp",116 "severity": "high",117 "isDirect": false,118 "via": [119 "cmake-js"120 ],121 "effects": [122 "qmd"123 ],124 "range": ">=2.4.0",125 "nodes": [126 "node_modules/node-llama-cpp"127 ],128 "fixAvailable": true129 },130 "qmd": {131 "name": "qmd",132 "severity": "high",133 "isDirect": true,134 "via": [135 "node-llama-cpp"136 ],137 "effects": [],138 "range": "",139 "nodes": [140 "node_modules/qmd"141 ],142 "fixAvailable": true143 },144 "qs": {145 "name": "qs",146 "severity": "low",147 "isDirect": false,148 "via": [149 {150 "source": 1113161,151 "name": "qs",152 "dependency": "qs",153 "title": "qs's arrayLimit bypass in comma parsing allows denial of service",154 "url": "https://github.com/advisories/GHSA-w7fw-mjwx-w883",155 "severity": "low",156 "cwe": [157 "CWE-20"158 ],159 "cvss": {160 "score": 3.7,161 "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L"162 },163 "range": ">=6.7.0 <=6.14.1"164 }165 ],166 "effects": [],167 "range": "6.7.0 - 6.14.1",168 "nodes": [169 "node_modules/qs"170 ],171 "fixAvailable": true172 },173 "tar": {174 "name": "tar",175 "severity": "high",176 "isDirect": false,177 "via": [178 {179 "source": 1112255,180 "name": "tar",181 "dependency": "tar",182 "title": "node-tar is Vulnerable to Arbitrary File Overwrite and Symlink Poisoning via Insufficient Path Sanitization",183 "url": "https://github.com/advisories/GHSA-8qq5-rm4j-mr97",184 "severity": "high",185 "cwe": [186 "CWE-22"187 ],188 "cvss": {189 "score": 0,190 "vectorString": null191 },192 "range": "<=7.5.2"193 },194 {195 "source": 1112329,196 "name": "tar",197 "dependency": "tar",198 "title": "Race Condition in node-tar Path Reservations via Unicode Ligature Collisions on macOS APFS",199 "url": "https://github.com/advisories/GHSA-r6q2-hw4h-h46w",200 "severity": "high",201 "cwe": [202 "CWE-176"203 ],204 "cvss": {205 "score": 8.8,206 "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L"207 },208 "range": "<=7.5.3"209 },210 {211 "source": 1112659,212 "name": "tar",213 "dependency": "tar",214 "title": "node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Traversal",215 "url": "https://github.com/advisories/GHSA-34x7-hfp2-rc4v",216 "severity": "high",217 "cwe": [218 "CWE-22",219 "CWE-59"220 ],221 "cvss": {222 "score": 8.2,223 "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N"224 },225 "range": "<7.5.7"226 }227 ],228 "effects": [229 "cmake-js"230 ],231 "range": "<=7.5.6",232 "nodes": [233 "node_modules/tar"234 ],235 "fixAvailable": true236 },237 "vite": {238 "name": "vite",239 "severity": "moderate",240 "isDirect": false,241 "via": [242 "esbuild"243 ],244 "effects": [245 "vite-node",246 "vitest"247 ],248 "range": "0.11.0 - 6.1.6",249 "nodes": [250 "node_modules/vite"251 ],252 "fixAvailable": {253 "name": "vitest",254 "version": "4.0.18",255 "isSemVerMajor": true256 }257 },258 "vite-node": {259 "name": "vite-node",260 "severity": "moderate",261 "isDirect": false,262 "via": [263 "vite"264 ],265 "effects": [266 "vitest"267 ],268 "range": "<=2.2.0-beta.2",269 "nodes": [270 "node_modules/vite-node"271 ],272 "fixAvailable": {273 "name": "vitest",274 "version": "4.0.18",275 "isSemVerMajor": true276 }277 },278 "vitest": {279 "name": "vitest",280 "severity": "moderate",281 "isDirect": true,282 "via": [283 "vite",284 "vite-node"285 ],286 "effects": [],287 "range": "0.0.1 - 0.0.12 || 0.0.29 - 0.0.122 || 0.3.3 - 2.2.0-beta.2",288 "nodes": [289 "node_modules/vitest"290 ],291 "fixAvailable": {292 "name": "vitest",293 "version": "4.0.18",294 "isSemVerMajor": true295 }296 }297 },298 "metadata": {299 "vulnerabilities": {300 "info": 0,301 "low": 1,302 "moderate": 4,303 "high": 6,304 "critical": 0,305 "total": 11306 },307 "dependencies": {308 "prod": 109,309 "dev": 173,310 "optional": 355,311 "peer": 278,312 "peerOptional": 0,313 "total": 561314 }315 }316}317318Process exited with code 1319✓ Completed in 164768ms
Files analyzed
Rules coverage147 patterns
Security Findings
Persistence mechanism installation
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/SKILL.md:31
Evidence: ~/.bashrc
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js:38
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js:63
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js:119
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js:123
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js:30
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js:44
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts:47
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts:55
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts:58
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts:69
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts:164
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts:180
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts:181
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts:182
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts:204
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.test.ts:89
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.ts:39
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.ts:80
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.test.ts:12
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.test.ts:12
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts:89
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts:218
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts:218
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts:38
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts:49
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts:49
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts:38
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts:40
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts:58
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.test.ts:8
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts:5
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts:7
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts:36
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts:80
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts:82
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts:187
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts:47
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts:49
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts:100
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts:117
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts:145
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.test.ts:10
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:27
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:47
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:49
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:60
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:95
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:95
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:113
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:155
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:155
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:180
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:180
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:185
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:188
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts:188
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/wake.ts:47
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.test.ts:12
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.test.ts:12
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts:16
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts:61
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts:61
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts:158
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts:162
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts:30
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts:36
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts:36
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/search.ts:180
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts:36
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts:43
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts:50
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts:50
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts:162
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts:162
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:41
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:71
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:166
Detected string concatenation with a non-literal variable in a util.format / console.log function. If an attacker injects a format specifier in the string, it will forge the log message. Try to use constant values for the format string.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:187
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:208
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:208
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:209
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:217
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:331
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:368
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:368
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:807
Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts:810
The MCP server is not in our registry.
Security issue in @modelcontextprotocol/sdk
Evidence: @modelcontextprotocol/sdk
Security issue in axios
Evidence: axios
Security issue in cmake-js
Evidence: cmake-js
Security issue in esbuild
Evidence: esbuild
Security issue in node-llama-cpp
Evidence: node-llama-cpp
Security issue in qmd
Evidence: qmd
Security issue in qs
Evidence: qs
Security issue in tar
Evidence: tar
Security issue in vite
Evidence: vite
Security issue in vite-node
Evidence: vite-node
Security issue in vitest
Evidence: vitest
Scan History1 scan
▸Failedv1.5.1Critical100 findings2/13/2026
Scanners5/5 ran
clawguard-rules▸1 finding2ms
View logs
1[2026-02-13T00:34:00.110Z] Running @yourclaw/clawguard-rules pattern matcher2Scanning: /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/SKILL.md3Content length: 5947 chars4Patterns matched: 15 [critical] MAL-006: Persistence mechanism installation6✓ Completed in 2ms
gitleaks▸0 findings152448ms
View logs
1[2026-02-13T00:36:32.558Z] $ gitleaks detect --source /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1 --report-format json --report-path /dev/stdout --no-git23⚠ stderr output:4○5 │╲6 │ ○7 ○ ░8 ░ gitleaks910[90m12:36AM[0m [31mFTL[0m [1mReport path is not writable: /dev/stdout[0m [36merror=[0m[31m[1m"open /dev/stdout: no such device or address"[0m[0m1112Process exited with code 113✓ Completed in 152448ms
semgrep▸87 findings215536ms
View logs
1[2026-02-13T00:37:35.649Z] $ semgrep scan --json --quiet --config auto /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-12{"version":"1.151.0","results":[{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":38,"col":46,"offset":896},"end":{"line":38,"col":55,"offset":905},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":63,"col":25,"offset":1540},"end":{"line":63,"col":34,"offset":1549},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":119,"col":77,"offset":3284},"end":{"line":119,"col":87,"offset":3294},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":123,"col":58,"offset":3430},"end":{"line":123,"col":68,"offset":3440},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js","start":{"line":30,"col":33,"offset":1020},"end":{"line":30,"col":42,"offset":1029},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js","start":{"line":44,"col":32,"offset":1333},"end":{"line":44,"col":40,"offset":1341},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":47,"col":25,"offset":1132},"end":{"line":47,"col":34,"offset":1141},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":55,"col":36,"offset":1362},"end":{"line":55,"col":39,"offset":1365},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":58,"col":30,"offset":1482},"end":{"line":58,"col":33,"offset":1485},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":69,"col":38,"offset":1836},"end":{"line":69,"col":41,"offset":1839},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":164,"col":30,"offset":4729},"end":{"line":164,"col":39,"offset":4738},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":180,"col":25,"offset":5181},"end":{"line":180,"col":34,"offset":5190},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":181,"col":30,"offset":5237},"end":{"line":181,"col":33,"offset":5240},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":182,"col":36,"offset":5296},"end":{"line":182,"col":39,"offset":5299},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","start":{"line":204,"col":38,"offset":5957},"end":{"line":204,"col":41,"offset":5960},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.test.ts","start":{"line":89,"col":48,"offset":2019},"end":{"line":89,"col":54,"offset":2025},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.ts","start":{"line":39,"col":36,"offset":1092},"end":{"line":39,"col":45,"offset":1101},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.ts","start":{"line":80,"col":46,"offset":2414},"end":{"line":80,"col":55,"offset":2423},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.test.ts","start":{"line":12,"col":30,"offset":412},"end":{"line":12,"col":34,"offset":416},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.test.ts","start":{"line":12,"col":36,"offset":418},"end":{"line":12,"col":44,"offset":426},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts","start":{"line":89,"col":76,"offset":3098},"end":{"line":89,"col":80,"offset":3102},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts","start":{"line":218,"col":34,"offset":7053},"end":{"line":218,"col":37,"offset":7056},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts","start":{"line":218,"col":39,"offset":7058},"end":{"line":218,"col":49,"offset":7068},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts","start":{"line":38,"col":33,"offset":1015},"end":{"line":38,"col":42,"offset":1024},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts","start":{"line":49,"col":31,"offset":1370},"end":{"line":49,"col":42,"offset":1381},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts","start":{"line":49,"col":44,"offset":1383},"end":{"line":49,"col":52,"offset":1391},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts","start":{"line":38,"col":28,"offset":1438},"end":{"line":38,"col":37,"offset":1447},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts","start":{"line":40,"col":32,"offset":1517},"end":{"line":40,"col":41,"offset":1526},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts","start":{"line":58,"col":32,"offset":2062},"end":{"line":58,"col":41,"offset":2071},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.test.ts","start":{"line":8,"col":48,"offset":269},"end":{"line":8,"col":54,"offset":275},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts","start":{"line":5,"col":30,"offset":147},"end":{"line":5,"col":39,"offset":156},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts","start":{"line":7,"col":34,"offset":209},"end":{"line":7,"col":41,"offset":216},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts","start":{"line":36,"col":67,"offset":1024},"end":{"line":36,"col":75,"offset":1032},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts","start":{"line":80,"col":30,"offset":1974},"end":{"line":80,"col":39,"offset":1983},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts","start":{"line":82,"col":33,"offset":2035},"end":{"line":82,"col":40,"offset":2042},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts","start":{"line":187,"col":44,"offset":5273},"end":{"line":187,"col":61,"offset":5290},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":47,"col":30,"offset":1192},"end":{"line":47,"col":39,"offset":1201},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":49,"col":33,"offset":1253},"end":{"line":49,"col":40,"offset":1260},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":100,"col":36,"offset":2729},"end":{"line":100,"col":45,"offset":2738},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":117,"col":44,"offset":3251},"end":{"line":117,"col":53,"offset":3260},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","start":{"line":145,"col":35,"offset":4095},"end":{"line":145,"col":50,"offset":4110},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.test.ts","start":{"line":10,"col":53,"offset":352},"end":{"line":10,"col":59,"offset":358},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":27,"col":35,"offset":728},"end":{"line":27,"col":43,"offset":736},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":47,"col":30,"offset":1238},"end":{"line":47,"col":35,"offset":1243},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":49,"col":33,"offset":1295},"end":{"line":49,"col":40,"offset":1302},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":60,"col":25,"offset":1594},"end":{"line":60,"col":42,"offset":1611},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":95,"col":33,"offset":2573},"end":{"line":95,"col":36,"offset":2576},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":95,"col":38,"offset":2578},"end":{"line":95,"col":48,"offset":2588},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":113,"col":41,"offset":3099},"end":{"line":113,"col":50,"offset":3108},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":155,"col":32,"offset":4557},"end":{"line":155,"col":35,"offset":4560},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":155,"col":37,"offset":4562},"end":{"line":155,"col":65,"offset":4590},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":180,"col":35,"offset":5257},"end":{"line":180,"col":38,"offset":5260},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":180,"col":40,"offset":5262},"end":{"line":180,"col":44,"offset":5266},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":185,"col":34,"offset":5443},"end":{"line":185,"col":43,"offset":5452},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":188,"col":32,"offset":5551},"end":{"line":188,"col":44,"offset":5563},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","start":{"line":188,"col":46,"offset":5565},"end":{"line":188,"col":74,"offset":5593},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/wake.ts","start":{"line":47,"col":34,"offset":1403},"end":{"line":47,"col":51,"offset":1420},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.test.ts","start":{"line":12,"col":30,"offset":450},"end":{"line":12,"col":34,"offset":454},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.test.ts","start":{"line":12,"col":36,"offset":456},"end":{"line":12,"col":44,"offset":464},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":16,"col":25,"offset":486},"end":{"line":16,"col":34,"offset":495},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":61,"col":34,"offset":1821},"end":{"line":61,"col":37,"offset":1824},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":61,"col":39,"offset":1826},"end":{"line":61,"col":49,"offset":1836},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":158,"col":30,"offset":4687},"end":{"line":158,"col":33,"offset":4690},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","start":{"line":162,"col":30,"offset":4861},"end":{"line":162,"col":39,"offset":4870},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts","start":{"line":30,"col":34,"offset":954},"end":{"line":30,"col":43,"offset":963},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts","start":{"line":36,"col":34,"offset":1172},"end":{"line":36,"col":44,"offset":1182},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts","start":{"line":36,"col":46,"offset":1184},"end":{"line":36,"col":50,"offset":1188},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/search.ts","start":{"line":180,"col":40,"offset":4527},"end":{"line":180,"col":44,"offset":4531},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":36,"col":44,"offset":734},"end":{"line":36,"col":51,"offset":741},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":43,"col":20,"offset":895},"end":{"line":43,"col":43,"offset":918},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":50,"col":20,"offset":1089},"end":{"line":50,"col":43,"offset":1112},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":50,"col":45,"offset":1114},"end":{"line":50,"col":64,"offset":1133},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":162,"col":32,"offset":3837},"end":{"line":162,"col":43,"offset":3848},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","start":{"line":162,"col":45,"offset":3850},"end":{"line":162,"col":49,"offset":3854},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":41,"col":26,"offset":938},"end":{"line":41,"col":35,"offset":947},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":71,"col":44,"offset":1737},"end":{"line":71,"col":52,"offset":1745},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":166,"col":52,"offset":4271},"end":{"line":166,"col":64,"offset":4283},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":187,"col":21,"offset":4984},"end":{"line":187,"col":52,"offset":5015},"extra":{"message":"Detected string concatenation with a non-literal variable in a util.format / console.log function. If an attacker injects a format specifier in the string, it will forge the log message. Try to use constant values for the format string.","metadata":{"cwe":["CWE-134: Use of Externally-Controlled Format String"],"owasp":["A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"category":"security","technology":["javascript"],"subcategory":["audit"],"likelihood":"MEDIUM","impact":"LOW","confidence":"LOW","references":["https://cwe.mitre.org/data/definitions/134.html"],"license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Improper Validation"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring","shortlink":"https://sg.run/7Y5R"},"severity":"INFO","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":208,"col":36,"offset":5474},"end":{"line":208,"col":44,"offset":5482},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":208,"col":46,"offset":5484},"end":{"line":208,"col":54,"offset":5492},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":209,"col":50,"offset":5544},"end":{"line":209,"col":62,"offset":5556},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":217,"col":54,"offset":5832},"end":{"line":217,"col":62,"offset":5840},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":331,"col":36,"offset":8768},"end":{"line":331,"col":42,"offset":8774},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":368,"col":37,"offset":9863},"end":{"line":368,"col":43,"offset":9869},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":368,"col":45,"offset":9871},"end":{"line":368,"col":49,"offset":9875},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":807,"col":30,"offset":22920},"end":{"line":807,"col":39,"offset":22929},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","start":{"line":810,"col":34,"offset":23014},"end":{"line":810,"col":41,"offset":23021},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}}],"errors":[],"paths":{"scanned":["/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/CHANGELOG.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/README.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/SKILL.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/_meta.json","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/docs/auto-linking.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/docs/context-death.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/HOOK.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/package-lock.json","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/package.json","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/checkpoint.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/doctor.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/entities.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/link.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/recover.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/repair-session.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/repair-session.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/setup.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/shell-init.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/sleep.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/status.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/template.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/commands/wake.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/index.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/auto-linker.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/backlinks.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/config.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/entity-index.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/search.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/search.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-repair.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/session-utils.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/template-engine.test.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/template-engine.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/time.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/types.ts","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/checkpoint.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/daily-note.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/daily.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/decision.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/handoff.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/lesson.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/person.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/templates/project.md","/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/tsconfig.json"]},"time":{"rules":[],"rules_parse_time":14.36149001121521,"profiling_times":{"config_time":18.34280824661255,"core_time":28.464223861694336,"ignores_time":0.0019006729125976562,"total_time":46.84109878540039},"parsing_time":{"total_time":0.0,"per_file_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_files":[]},"scanning_time":{"total_time":19.270215272903442,"per_file_time":{"mean":0.12513126800586644,"std_dev":0.2822323039759363},"very_slow_stats":{"time_ratio":0.5083798864019303,"count_ratio":0.01948051948051948},"very_slow_files":[{"fpath":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/hooks/clawvault/handler.js","ftime":1.714353084564209},{"fpath":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/src/lib/vault.ts","ftime":2.196131944656372},{"fpath":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","ftime":5.8861048221588135}]},"matching_time":{"total_time":0.0,"per_file_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_files":[]},"tainting_time":{"total_time":0.0,"per_def_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_defs":[]},"fixpoint_timeouts":[{"error_type":"Fixpoint timeout","severity":"warn","message":"Fixpoint timeout while performing taint analysis at /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js:1:0 [rules: 4, first: javascript.lang.security.audit.dangerous-spawn-shell.dangerous-spawn-shell]","location":{"path":"/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1/bin/clawvault.js","start":{"line":1,"col":1,"offset":0},"end":{"line":1,"col":1,"offset":0}}}],"prefiltering":{"project_level_time":0.0,"file_level_time":0.0,"rules_with_project_prefilters_ratio":0.0,"rules_with_file_prefilters_ratio":0.9862007567326952,"rules_selected_ratio":0.03271756064989984,"rules_matched_ratio":0.03271756064989984},"targets":[],"total_bytes":0,"max_memory_bytes":1449516736},"engine_requested":"OSS","skipped_rules":[],"profiling_results":[]}34Process exited with code 05✓ Completed in 215536ms
mcp-scan▸1 finding165276ms
View logs
1[2026-02-13T00:36:45.392Z] $ mcp-scan --skills /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1 --json2{3 "/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt": {4 "client": "not-available",5 "path": "/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt",6 "servers": [7 {8 "name": "2026-02-10-clawhub-clawvault-1-5-1",9 "server": {10 "path": "/tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-1",11 "type": "skill"12 },13 "signature": {14 "metadata": {15 "meta": null,16 "protocolVersion": "built-in",17 "capabilities": {18 "experimental": null,19 "logging": null,20 "prompts": null,21 "resources": null,22 "tools": {23 "listChanged": false24 },25 "completions": null,26 "tasks": null27 },28 "serverInfo": {29 "name": "clawvault",30 "title": null,31 "version": "skills",32 "websiteUrl": null,33 "icons": null34 },35 "instructions": "Structured memory system for OpenClaw agents. Context death resilience (checkpoint/recover), structured storage, Obsidian-compatible markdown, local semantic search, and session transcript repair.",36 "prompts": {37 "listChanged": false38 },39 "resources": {40 "subscribe": null,41 "listChanged": false42 }43 },44 "prompts": [45 {46 "name": "SKILL.md",47 "title": null,48 "description": "\n\n# ClawVault \ud83d\udc18\n\nAn elephant never forgets. Structured memory for OpenClaw agents.\n\n> **Built for [OpenClaw](https://openclaw.ai)** \u2014 install via `clawhub install clawvault`\n\n## Install\n\n```bash\nnpm install -g clawvault\n```\n\n## Setup\n\n```bash\n# Initialize vault (creates folder structure + templates)\nclawvault init ~/my-vault\n\n# Or set env var to use existing vault\nexport CLAWVAULT_PATH=/path/to/memory\n\n# Optional: shell integration (aliases + CLAWVAULT_PATH)\nclawvault shell-init >> ~/.bashrc\n```\n\n## Quick Start for New Agents\n\n```bash\n# Start your session (recover + recap + summary)\nclawvault wake\n\n# Capture and checkpoint during work\nclawvault capture \"TODO: Review PR tomorrow\"\nclawvault checkpoint --working-on \"PR review\" --focus \"type guards\"\n\n# End your session with a handoff\nclawvault sleep \"PR review + type guards\" --next \"respond to CI\" --blocked \"waiting for CI\"\n\n# Health check when something feels off\nclawvault doctor\n```\n\n## Core Commands\n\n### Wake + Sleep (primary)\n\n```bash\nclawvault wake\nclawvault sleep \"what I was working on\" --next \"ship v1\" --blocked \"waiting for API key\"\n```\n\n### Store memories by type\n\n```bash\n# Types: fact, feeling, decision, lesson, commitment, preference, relationship, project\nclawvault remember decision \"Use Postgres over SQLite\" --content \"Need concurrent writes for multi-agent setup\"\nclawvault remember lesson \"Context death is survivable\" --content \"Checkpoint before heavy work\"\nclawvault remember relationship \"Justin Dukes\" --content \"Client contact at Hale Pet Door\"\n```\n\n### Quick capture to inbox\n\n```bash\nclawvault capture \"TODO: Review PR tomorrow\"\n```\n\n### Search (requires qmd installed)\n\n```bash\n# Keyword search (fast)\nclawvault search \"client contacts\"\n\n# Semantic search (slower, more accurate)\nclawvault vsearch \"what did we decide about the database\"\n```\n\n## Context Death Resilience\n\n### Wake (start of session)\n\n```bash\nclawvault wake\n```\n\n### Sleep (end of session)\n\n```bash\nclawvault sleep \"what I was working on\" --next \"finish docs\" --blocked \"waiting for review\"\n```\n\n### Checkpoint (save state frequently)\n\n```bash\nclawvault checkpoint --working-on \"PR review\" --focus \"type guards\" --blocked \"waiting for CI\"\n```\n\n### Recover (manual check)\n\n```bash\nclawvault recover --clear\n# Shows: death time, last checkpoint, recent handoff\n```\n\n### Handoff (manual session end)\n\n```bash\nclawvault handoff \\\n --working-on \"ClawVault improvements\" \\\n --blocked \"npm token\" \\\n --next \"publish to npm, create skill\" \\\n --feeling \"productive\"\n```\n\n### Recap (bootstrap new session)\n\n```bash\nclawvault recap\n# Shows: recent handoffs, active projects, pending commitments, lessons\n```\n\n## Auto-linking\n\nWiki-link entity mentions in markdown files:\n\n```bash\n# Link all files\nclawvault link --all\n\n# Link single file\nclawvault link memory/2024-01-15.md\n```\n\n## Folder Structure\n\n```\nvault/\n\u251c\u2500\u2500 .clawvault/ # Internal state\n\u2502 \u251c\u2500\u2500 last-checkpoint.json\n\u2502 \u2514\u2500\u2500 dirty-death.flag\n\u251c\u2500\u2500 decisions/ # Key choices with reasoning\n\u251c\u2500\u2500 lessons/ # Insights and patterns\n\u251c\u2500\u2500 people/ # One file per person\n\u251c\u2500\u2500 projects/ # Active work tracking\n\u251c\u2500\u2500 handoffs/ # Session continuity\n\u251c\u2500\u2500 inbox/ # Quick captures\n\u2514\u2500\u2500 templates/ # Document templates\n```\n\n## Best Practices\n\n1. **Wake at session start** \u2014 `clawvault wake` restores context\n2. **Checkpoint every 10-15 min** during heavy work\n3. **Sleep before session end** \u2014 `clawvault sleep` captures next steps\n4. **Use types** \u2014 knowing WHAT you're storing helps WHERE to put it\n5. **Wiki-link liberally** \u2014 `[[person-name]]` builds your knowledge graph\n\n## Checklist for AGENTS.md\n\n```markdown\n## Memory Checklist\n- [ ] Run `clawvault wake` at session start\n- [ ] Checkpoint during heavy work\n- [ ] Capture key decisions/lessons with `clawvault remember`\n- [ ] Use wiki-links like `[[person-name]]`\n- [ ] End with `clawvault sleep \"...\" --next \"...\" --blocked \"...\"`\n- [ ] Run `clawvault doctor` when something feels off\n```\n\n## Session Transcript Repair (v1.5.0+)\n\nWhen the Anthropic API rejects with \"unexpected tool_use_id found in tool_result blocks\", use:\n\n```bash\n# See what's wrong (dry-run)\nclawvault repair-session --dry-run\n\n# Fix it\nclawvault repair-session\n\n# Repair a specific session\nclawvault repair-session --session <id> --agent <agent-id>\n\n# List available sessions\nclawvault repair-session --list\n```\n\n**What it fixes:**\n- Orphaned `tool_result` blocks referencing non-existent `tool_use` IDs\n- Aborted tool calls with partial JSON\n- Broken parent chain references\n\nBackups are created automatically (use `--no-backup` to skip).\n\n## Troubleshooting\n\n- **qmd not installed** \u2014 run `bun install -g github:tobi/qmd` or `npm install -g qmd`\n- **No ClawVault found** \u2014 run `clawvault init` or set `CLAWVAULT_PATH`\n- **CLAWVAULT_PATH missing** \u2014 run `clawvault shell-init` and add to shell rc\n- **Too many orphan links** \u2014 run `clawvault link --orphans`\n- **Inbox backlog warning** \u2014 process or archive inbox items\n- **\"unexpected tool_use_id\" error** \u2014 run `clawvault repair-session`\n\n## Integration with qmd\n\nClawVault uses [qmd](https://github.com/tobi/qmd) for search:\n\n```bash\n# Install qmd\nbun install -g github:tobi/qmd\n\n# Add vault as collection\nqmd collection add /path/to/vault --name my-memory --mask \"**/*.md\"\n\n# Update index\nqmd update && qmd embed\n```\n\n## Environment Variables\n\n- `CLAWVAULT_PATH` \u2014 Default vault path (skips auto-discovery)\n\n## Links\n\n- npm: https://www.npmjs.com/package/clawvault\n- GitHub: https://github.com/Versatly/clawvault\n- Issues: https://github.com/Versatly/clawvault/issues\n",49 "arguments": [],50 "icons": null,51 "meta": null52 },53 {54 "name": "templates/decision.md",55 "title": null,56 "description": "---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\nstatus: decided\n---\n\n# Decision: {{title}}\n\n## Context\n- \n\n## Decision\n- \n\n## Consequences\n- \n",57 "arguments": null,58 "icons": null,59 "meta": null60 },61 {62 "name": "templates/handoff.md",63 "title": null,64 "description": "---\ntitle: \"Handoff {{datetime}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# Session Handoff\n\n## Working On\n- \n\n## Blocked\n- \n\n## Next\n- [ ]\n\n## Notes\n- \n",65 "arguments": null,66 "icons": null,67 "meta": null68 },69 {70 "name": "templates/person.md",71 "title": null,72 "description": "---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\nrelationship: contact\n---\n\n# {{title}}\n\n## Context\n- \n\n## Details\n- Contact:\n- Role:\n- Timezone:\n\n## History\n- {{date}}: \n",73 "arguments": null,74 "icons": null,75 "meta": null76 },77 {78 "name": "templates/daily.md",79 "title": null,80 "description": "---\ntitle: \"{{date}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# {{date}}\n\n## Focus\n- \n\n## Wins\n- \n\n## Notes\n- \n\n## Next\n- [ ]\n",81 "arguments": null,82 "icons": null,83 "meta": null84 },85 {86 "name": "templates/lesson.md",87 "title": null,88 "description": "---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# Lesson: {{title}}\n\n## Insight\n- \n\n## Evidence\n- \n\n## Application\n- \n",89 "arguments": null,90 "icons": null,91 "meta": null92 },93 {94 "name": "templates/daily-note.md",95 "title": null,96 "description": "---\ntitle: \"{{date}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# {{date}}\n\n## Focus\n- \n\n## Wins\n- \n\n## Notes\n- \n\n## Next\n- [ ]\n",97 "arguments": null,98 "icons": null,99 "meta": null100 },101 {102 "name": "templates/checkpoint.md",103 "title": null,104 "description": "---\ntitle: \"Checkpoint {{datetime}}\"\ndate: {{date}}\ntype: {{type}}\n---\n\n# Checkpoint\n\n## Working On\n- \n\n## Focus\n- \n\n## Blocked\n- \n\n## Notes\n- \n",105 "arguments": null,106 "icons": null,107 "meta": null108 },109 {110 "name": "templates/project.md",111 "title": null,112 "description": "---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\nstatus: active\n---\n\n# {{title}}\n\n## Objective\n- \n\n## Status\n- [ ] Planning\n- [ ] In progress\n- [ ] Blocked\n- [ ] Done\n\n## Next\n- [ ]\n\n## Notes\n- \n",113 "arguments": null,114 "icons": null,115 "meta": null116 },117 {118 "name": "README.md",119 "title": null,120 "description": "# ClawVault \ud83d\udc18\n\n**An elephant never forgets.**\n\nStructured memory system for AI agents. Store, search, and link memories across sessions.\n\n> **Built for [OpenClaw](https://openclaw.ai)** \u2014 the AI agent framework. Works standalone too.\n\n## Install for OpenClaw Agents\n\n```bash\n# Install the skill (recommended for OpenClaw agents)\nclawhub install clawvault\n\n# Or install the CLI globally\nnpm install -g clawvault\n```\n\n## Requirements\n\n- **Node.js 18+**\n- **[qmd](https://github.com/Versatly/qmd)** \u2014 Local semantic search (required)\n\n```bash\n# Install qmd first\nbun install -g qmd # or: npm install -g qmd\n\n# Then install clawvault\nnpm install -g clawvault\n```\n\n## Why ClawVault?\n\nAI agents forget things. Context windows overflow, sessions end, important details get lost. ClawVault fixes that:\n\n- **Structured storage** \u2014 Organized categories, not random notes\n- **Local search** \u2014 qmd provides BM25 + semantic search with local embeddings (no API quotas)\n- **Wiki-links** \u2014 `[[connections]]` visible in Obsidian's graph view\n- **Session continuity** \u2014 Handoff/recap system for context death\n- **Token efficient** \u2014 Search instead of loading entire memory files\n\n## Quick Start\n\n```bash\n# Initialize vault with qmd collection\nclawvault init ~/memory --qmd-collection my-memory\n\n# Store memories\nclawvault remember decision \"Use qmd\" --content \"Local embeddings, no API limits\"\nclawvault remember lesson \"Context death is survivable\" --content \"Write it down\"\nclawvault capture \"Quick note to process later\"\n\n# Search (uses qmd)\nclawvault search \"decision\" # BM25 keyword search\nclawvault vsearch \"what did I decide\" # Semantic search\n\n# Session management\nclawvault wake\nclawvault sleep \"build wake/sleep commands\" --next \"run doctor\"\nclawvault handoff --working-on \"task1\" --next \"task2\" # Manual handoff (advanced)\nclawvault recap # Manual recap (advanced)\n```\n\n**Tip:** Set `CLAWVAULT_PATH` to skip directory walk (or use `shell-init`):\n```bash\necho 'export CLAWVAULT_PATH=\"$HOME/memory\"' >> ~/.bashrc\neval \"$(clawvault shell-init)\"\n```\n\n## Search: qmd vs memory_search\n\n**Use `qmd` (or `clawvault search`) \u2014 not `memory_search`**\n\n| Tool | Backend | Speed | API Limits |\n|------|---------|-------|------------|\n| `qmd search` / `clawvault search` | Local BM25 | Instant | None |\n| `qmd vsearch` / `clawvault vsearch` | Local embeddings | Fast | None |\n| `memory_search` | Gemini API | Variable | **Yes, hits quotas** |\n\n```bash\n# \u2705 Use this\nqmd search \"query\" -c my-memory\nclawvault search \"query\"\n\n# \u274c Avoid (API quotas)\nmemory_search\n```\n\n## Vault Structure\n\n```\nmy-memory/\n\u251c\u2500\u2500 .clawvault.json # Config (includes qmd collection name)\n\u251c\u2500\u2500 decisions/ # Choices with reasoning\n\u251c\u2500\u2500 lessons/ # Things learned\n\u251c\u2500\u2500 people/ # One file per person\n\u251c\u2500\u2500 projects/ # Active work\n\u251c\u2500\u2500 commitments/ # Promises and deadlines\n\u251c\u2500\u2500 inbox/ # Quick capture (process later)\n\u2514\u2500\u2500 handoffs/ # Session continuity\n```\n\n## Commands\n\n### Store Memories\n\n```bash\n# With type classification (recommended)\nclawvault remember <type> <title> --content \"...\"\n# Types: decision, lesson, fact, commitment, project, person\n\n# Quick capture\nclawvault capture \"Note to self\"\n\n# Manual store\nclawvault store -c decisions -t \"Title\" --content \"...\"\n```\n\n**Note:** All write commands auto-update the qmd index. Use `--no-index` to skip.\n\n### Search\n\n```bash\nclawvault search \"query\" # BM25 keyword\nclawvault search \"query\" -c people # Filter by category\nclawvault vsearch \"query\" # Semantic (local embeddings)\n```\n\n### Browse\n\n```bash\nclawvault list # All documents\nclawvault list decisions # By category\nclawvault get decisions/title # Specific document\nclawvault stats # Vault overview\n```\n\n### Session Continuity\n\n```bash\n# Start a session (recover + recap + summary)\nclawvault wake\n\n# End a session with a handoff\nclawvault sleep \"building CRM, fixing webhook\" \\\n --blocked \"waiting for API key\" \\\n --next \"deploy to production\" \\\n --decisions \"chose Supabase over Firebase\" \\\n --feeling \"focused\"\n\n# Manual tools (advanced)\nclawvault handoff --working-on \"task1\" --next \"task2\"\nclawvault recap --brief # Token-efficient recap\n\n# Health check\nclawvault doctor\n```\n\n## Agent Setup (AGENTS.md)\n\nAdd this to your `AGENTS.md` to ensure proper memory habits:\n\n```markdown\n## Memory\n\n**Write everything down. Memory doesn't survive session restarts.**\n\n### Search (use qmd, not memory_search)\n\\`\\`\\`bash\nqmd search \"query\" -c your-memory # Fast keyword\nqmd vsearch \"query\" -c your-memory # Semantic\n\\`\\`\\`\n\n### Store\n\\`\\`\\`bash\nclawvault remember decision \"Title\" --content \"...\"\nclawvault remember lesson \"Title\" --content \"...\"\n\\`\\`\\`\n\n### Session Start\n\\`\\`\\`bash\nclawvault wake\n\\`\\`\\`\n\n### Session End\n\\`\\`\\`bash\nclawvault sleep \"...\" --next \"...\"\n\\`\\`\\`\n\n### Checkpoint (during heavy work)\n\\`\\`\\`bash\nclawvault checkpoint --working-on \"...\" --focus \"...\" --blocked \"...\"\n\\`\\`\\`\n\n### Why qmd over memory_search?\n- Local embeddings \u2014 no API quotas\n- Always works \u2014 no external dependencies\n- Fast \u2014 instant BM25, quick semantic\n```\n\n## Templates\n\nClawVault includes templates for common memory types:\n\n- `decision.md` \u2014 Choices with context and reasoning\n- `lesson.md` \u2014 Things learned\n- `person.md` \u2014 People you work with\n- `project.md` \u2014 Active work\n- `handoff.md` \u2014 Session state before context death\n- `daily.md` \u2014 Daily notes\n\nUse with: `clawvault store -c category -t \"Title\" -f decision`\n\n## Library Usage\n\n```typescript\nimport { ClawVault, createVault, findVault } from 'clawvault';\n\nconst vault = await createVault('./memory', { qmdCollection: 'my-memory' });\n\nawait vault.store({\n category: 'decisions',\n title: 'Use ClawVault',\n content: 'Decided to use ClawVault for memory.',\n});\n\nconst results = await vault.find('memory', { limit: 5 });\n```\n\n## License\n\nMIT\n\n---\n\n*\"An elephant never forgets.\" \u2014 Now neither do you.* \ud83d\udc18\n",121 "arguments": null,122 "icons": null,123 "meta": null124 },125 {126 "name": "CHANGELOG.md",127 "title": null,128 "description": "# Changelog\n\n## [1.5.1] - 2026-02-06\n\n### Security\n- **Fixed shell injection vulnerability** in hooks/clawvault/handler.js\n - Changed from `execSync` (with shell) to `execFileSync` (no shell)\n - All arguments passed as array, never interpolated into shell string\n - Vault path validation: must be absolute, exist, and contain .clawvault.json\n\n- **Fixed prompt injection vulnerability**\n - Checkpoint recovery data now sanitized before injection\n - Control characters stripped, markdown escaped, length limited\n - Session keys and command sources sanitized with strict allowlist\n\n- **Removed direct GitHub dependency** for qmd\n - qmd moved to optional peer dependency\n - Users install separately: `npm install -g github:tobi/qmd`\n - ClawVault gracefully handles missing qmd\n\n### Changed\n- Hook now validates vault paths before use\n- Error messages in hooks are now generic (no sensitive data leaked)\n\n---\n\n## [1.5.0] - 2026-02-06\n\n### Added\n- **`clawvault repair-session`** - Repair corrupted OpenClaw session transcripts\n - Detects orphaned `tool_result` blocks that reference non-existent `tool_use` IDs\n - Identifies aborted tool calls with partial JSON\n - Automatically relinks parent chain after removals\n - Creates backup before repair (configurable with `--no-backup`)\n - Dry-run mode with `--dry-run` to preview repairs\n - List sessions with `--list` flag\n - JSON output with `--json` for scripting\n \n **Problem solved:** When the Anthropic API rejects with \"unexpected tool_use_id found in tool_result blocks\", this command fixes the transcript so the session can continue without losing context.\n \n ```bash\n # Analyze without changing\n clawvault repair-session --dry-run\n \n # Repair current main session\n clawvault repair-session\n \n # Repair specific session\n clawvault repair-session --session <id> --agent <agent-id>\n ```\n\n- **Session utilities** (`src/lib/session-utils.ts`)\n - `listAgents()` - Find all agents in ~/.openclaw/agents/\n - `findMainSession()` - Get current session for an agent\n - `findSessionById()` - Look up specific session\n - `getSessionFilePath()`, `backupSession()` - File helpers\n\n### Tests\n- Added 13 tests for session repair functionality\n - Transcript parsing\n - Tool use extraction from assistant messages\n - Corruption detection (aborted + orphaned)\n - Parent chain relinking\n - Dry-run mode\n - Backup creation\n\n---\n\n## [1.4.2] - 2026-02-06\n\n### Added\n- **OpenClaw Hook Integration** - Automatic context death resilience\n - `gateway:startup` event: Detects if previous session died, injects alert into first agent turn\n - `command:new` event: Auto-checkpoints before session reset\n - Install: `openclaw hooks install clawvault && openclaw hooks enable clawvault`\n - Hook ships with npm package via `openclaw.hooks` field in package.json\n\n- **`clawvault wake`** - All-in-one session start command\n - Combines: `recover --clear` + `recap` + summary\n - Shows context death status, recent handoffs, what you were working on\n - Perfect for session startup ritual\n\n- **`clawvault sleep <summary>`** - All-in-one session end command\n - Creates handoff with: --next, --blocked, --decisions, --questions, --feeling\n - Clears death flag\n - Optional git commit prompt (--no-git to skip)\n - Captures rich context before ending session\n\n### Fixed\n- Fixed readline import in sleep command (was using `readline/promises` which bundlers couldn't resolve)\n\n### Changed\n- Documentation updated for hook-first approach\n- AGENTS.md simplified - hook handles basics, manual commands for rich context\n- SKILL.md updated with OpenClaw Integration section\n\n---\n\n## [1.4.1] - 2026-02-05\n\n### Added\n- `clawvault doctor` - Vault health diagnostics\n- `clawvault shell-init` - Shell integration setup\n\n---\n\n## [1.4.0] - 2026-02-04\n\n### Added\n- **qmd integration** - Semantic search via local embeddings\n- `clawvault setup` - Auto-discovers OpenClaw memory folder\n- `clawvault status` - Vault health, checkpoint age, qmd index\n- `clawvault template` - List/create/add with 7 built-in templates\n- `clawvault link --backlinks` - See what links to a file\n- `clawvault link --orphans` - Find broken wiki-links\n\n### Changed\n- qmd is now required for semantic search functionality\n\n---\n\n## [1.3.x] - Earlier\n\n- Initial release with core functionality\n- Checkpoint/recover for context death resilience\n- Handoff/recap for session continuity\n- Wiki-linking and entity management\n- Structured memory categories\n",129 "arguments": null,130 "icons": null,131 "meta": null132 },133 {134 "name": "docs/context-death.md",135 "title": null,136 "description": "# Context Death Resilience\n\n**Problem:** When an agent hits context overflow, it dies mid-thought with no chance to save state. The next session starts fresh with no memory of what was happening.\n\n**Solution:** Multi-layered defense against context death.\n\n## Architecture\n\n### Layer 1: Periodic Checkpoints (HEARTBEAT)\n- Add `clawvault checkpoint` to HEARTBEAT.md\n- Quick, lightweight save every few heartbeats\n- Captures: working-on, recent decisions, current focus\n\n### Layer 2: Pre-Compaction Flush\n- OpenClaw already has `compaction.memoryFlush`\n- Hook into this to also run `clawvault handoff --pre-compact`\n- Gives agent one last chance to save before context shrinks\n\n### Layer 3: Emergency Handoff (Gateway Hook)\n- New hook: `agent:context_overflow`\n- Runs `clawvault emergency-save` from last known state\n- Parses session transcript to extract what was happening\n- Works even when agent can't respond\n\n### Layer 4: Auto-Recap on Bootstrap\n- Check for \"dirty death\" flag on startup\n- If found, inject recap + context death notice\n- Agent knows it died and can resume\n\n## Commands\n\n### `clawvault checkpoint`\nQuick state save (runs in <1s):\n```bash\nclawvault checkpoint --working-on \"docs study\" --focus \"config parsing\"\n```\n\n### `clawvault emergency-save`\nCalled by gateway when context overflows:\n```bash\nclawvault emergency-save --session-file ~/.openclaw/sessions/xxx.jsonl\n```\n- Parses last N messages from transcript\n- Extracts what agent was doing\n- Creates emergency handoff\n\n### `clawvault recover`\nCheck for dirty death and get recovery info:\n```bash\nclawvault recover\n# Returns: { died: true, recap: \"...\", lastHandoff: \"...\" }\n```\n\n## State Files\n\n```\nmemory/\n\u251c\u2500\u2500 .clawvault/\n\u2502 \u251c\u2500\u2500 session-state.json # Current session tracker\n\u2502 \u251c\u2500\u2500 last-checkpoint.json # Quick checkpoint data\n\u2502 \u2514\u2500\u2500 dirty-death.flag # Set on crash, cleared on clean exit\n```\n\n## Integration Points\n\n### AGENTS.md Bootstrap\n```markdown\n## Every Session\n1. Run `clawvault recover` - check if last session died\n2. If died: load emergency handoff, acknowledge context death\n3. Run `clawvault recap` for normal continuity\n```\n\n### HEARTBEAT.md\n```markdown\n## Checkpoint (every 4-6 heartbeats)\n- Run `clawvault checkpoint` with current focus\n```\n\n### OpenClaw Hook (context-death-handler)\n```typescript\nconst handler: HookHandler = async (event) => {\n if (event.type === 'agent' && event.action === 'context_overflow') {\n await execSync('clawvault emergency-save --session-file ' + event.context.sessionFile);\n }\n};\n```\n\n## Implementation Priority\n\n1. \u2705 `clawvault handoff` - Already exists\n2. \ud83d\udd32 `clawvault checkpoint` - Quick version of handoff\n3. \ud83d\udd32 `clawvault emergency-save` - Parse transcript on crash\n4. \ud83d\udd32 `clawvault recover` - Detect dirty death\n5. \ud83d\udd32 OpenClaw hook - Trigger emergency save\n6. \ud83d\udd32 Bootstrap integration - Auto-inject on restart\n\n## Open Questions\n\n- Does OpenClaw emit an event on context overflow? Need to check.\n- Can we detect \"about to overflow\" before it happens?\n- Should checkpoint be a cron job or HEARTBEAT task?\n",137 "arguments": null,138 "icons": null,139 "meta": null140 },141 {142 "name": "docs/auto-linking.md",143 "title": null,144 "description": "# ClawVault Auto-Linking Spec\n\n## Problem\nAgents forget to use `[[wiki-links]]` when writing memories, making the Obsidian graph sparse and connections invisible.\n\n## Solution: Automatic Entity Linking\n\n### 1. Entity Registry (`memory/.entities.json`)\n```json\n{\n \"people\": {\n \"pedro\": {\n \"path\": \"people/pedro\",\n \"aliases\": [\"Pedro\", \"Chief\", \"my human\", \"the boss\"]\n },\n \"justin-dukes\": {\n \"path\": \"people/justin-dukes\", \n \"aliases\": [\"Justin\", \"Justin Dukes\", \"Hale contact\"]\n }\n },\n \"projects\": {\n \"site-machine\": {\n \"path\": \"projects/site-machine\",\n \"aliases\": [\"Site Machine\", \"the business\", \"income project\"]\n }\n },\n \"agents\": {\n \"forge\": {\n \"path\": \"agents/forge\",\n \"aliases\": [\"Forge\", \"business agent\", \"the sales agent\"]\n }\n }\n}\n```\n\n### 2. Auto-Link on Write\nWhen `clawvault remember` saves a file:\n1. Load entity registry\n2. Scan content for alias matches (case-insensitive, word-boundary)\n3. Replace first occurrence of each entity with `[[path|alias]]`\n4. Skip if already inside a link or code block\n\n### 3. CLI Commands\n```bash\n# Register new entity\nclawvault entity add pedro --path people/pedro --aliases \"Pedro,Chief,my human\"\n\n# Link a single file\nclawvault link memory/2026-01-31.md\n\n# Link all files in vault\nclawvault link --all\n\n# Show unlinked entity mentions\nclawvault link --dry-run\n```\n\n### 4. Integration Points\n- `clawvault remember` \u2014 auto-link before write\n- `clawvault handoff` \u2014 auto-link the handoff content\n- New `clawvault link` command for batch processing\n\n### 5. Edge Cases\n- Don't link inside code blocks or frontmatter\n- Don't double-link (check if text is already `[[linked]]`)\n- Prefer longer aliases first (\"Justin Dukes\" before \"Justin\")\n- Only link first occurrence per entity per file (avoid spam)\n\n## Implementation Priority\n1. Entity registry JSON structure\n2. `clawvault entity add/list/remove` commands\n3. Link scanner utility\n4. Integration with `remember` command\n5. Batch `link --all` command\n",145 "arguments": null,146 "icons": null,147 "meta": null148 },149 {150 "name": "hooks/clawvault/HOOK.md",151 "title": null,152 "description": "---\nname: clawvault\ndescription: \"Context death resilience - auto-checkpoint and recovery detection\"\nmetadata:\n openclaw:\n emoji: \"\ud83d\udc18\"\n events: [\"gateway:startup\", \"command:new\"]\n requires:\n bins: [\"clawvault\"]\n---\n\n# ClawVault Hook\n\nIntegrates ClawVault's context death resilience into OpenClaw:\n\n- **On gateway startup**: Checks for context death, alerts agent\n- **On /new command**: Auto-checkpoints before session reset\n\n## Installation\n\n```bash\nnpm install -g clawvault\nopenclaw hooks install clawvault\nopenclaw hooks enable clawvault\n```\n\n## Requirements\n\n- ClawVault CLI installed globally\n- Vault initialized (`clawvault setup` or `CLAWVAULT_PATH` set)\n\n## What It Does\n\n### Gateway Startup\n\n1. Runs `clawvault recover --clear`\n2. If context death detected, injects warning into first agent turn\n3. Clears dirty death flag for clean session start\n\n### Command: /new\n\n1. Creates automatic checkpoint with session info\n2. Captures state even if agent forgot to handoff\n3. Ensures continuity across session resets\n\n## No Configuration Needed\n\nJust enable the hook. It auto-detects vault path via:\n\n1. `CLAWVAULT_PATH` environment variable\n2. Walking up from cwd to find `.clawvault.json`\n",153 "arguments": null,154 "icons": null,155 "meta": null156 }157 ],158 "resources": [159 {160 "name": "package.json",161 "title": null,162 "uri": "skill://package.json",163 "description": "{\n \"name\": \"clawvault\",\n \"version\": \"1.5.1\",\n \"description\": \"\ud83d\udc18 An elephant never forgets. Structured memory for OpenClaw agents. Context death resilience, Obsidian-compatible markdown, local semantic search.\",\n \"type\": \"module\",\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"bin\": {\n \"clawvault\": \"./bin/clawvault.js\"\n },\n \"files\": [\n \"dist\",\n \"bin\",\n \"templates\",\n \"hooks\"\n ],\n \"openclaw\": {\n \"hooks\": [\n \"./hooks/clawvault\"\n ]\n },\n \"scripts\": {\n \"build\": \"tsup src/index.ts src/commands/entities.ts src/commands/link.ts src/commands/checkpoint.ts src/commands/recover.ts src/commands/status.ts src/commands/template.ts src/commands/setup.ts src/commands/wake.ts src/commands/sleep.ts src/commands/doctor.ts src/commands/shell-init.ts src/commands/repair-session.ts src/lib/entity-index.ts src/lib/auto-linker.ts src/lib/config.ts src/lib/template-engine.ts src/lib/session-utils.ts src/lib/session-repair.ts --format esm --dts --clean\",\n \"dev\": \"tsup src/index.ts src/commands/*.ts src/lib/*.ts --format esm --dts --watch\",\n \"lint\": \"eslint src\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"keywords\": [\n \"openclaw\",\n \"ai\",\n \"agent\",\n \"memory\",\n \"vault\",\n \"obsidian\",\n \"markdown\",\n \"semantic-search\",\n \"context-death\",\n \"llm\"\n ],\n \"author\": \"Versatly\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Versatly/clawvault.git\"\n },\n \"homepage\": \"https://github.com/Versatly/clawvault#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/Versatly/clawvault/issues\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"dependencies\": {\n \"commander\": \"^12.0.0\",\n \"chalk\": \"^5.3.0\",\n \"glob\": \"^10.3.10\",\n \"gray-matter\": \"^4.0.3\",\n \"natural\": \"^6.10.4\"\n },\n \"optionalDependencies\": {},\n \"peerDependencies\": {\n \"qmd\": \"*\"\n },\n \"peerDependenciesMeta\": {\n \"qmd\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.11.0\",\n \"tsup\": \"^8.0.1\",\n \"typescript\": \"^5.3.3\",\n \"vitest\": \"^1.2.0\"\n }\n}\n",164 "mimeType": null,165 "size": null,166 "icons": null,167 "annotations": null,168 "meta": null169 },170 {171 "name": "_meta.json",172 "title": null,173 "uri": "skill://_meta.json",174 "description": "{\n \"owner\": \"pin-alt\",\n \"slug\": \"2026-02-10-clawhub-clawvault-1-5-1\",\n \"displayName\": \"2026 02 10 Clawhub Clawvault 1.5.1\",\n \"latest\": {\n \"version\": \"1.0.0\",\n \"publishedAt\": 1770876286850,\n \"commit\": \"https://github.com/openclaw/skills/commit/17c27532596fd1a4dbb81c5b1fcd063f878c827e\"\n },\n \"history\": []\n}\n",175 "mimeType": null,176 "size": null,177 "icons": null,178 "annotations": null,179 "meta": null180 },181 {182 "name": "tsconfig.json",183 "title": null,184 "uri": "skill://tsconfig.json",185 "description": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"NodeNext\",\n \"moduleResolution\": \"NodeNext\",\n \"lib\": [\"ES2022\"],\n \"declaration\": true,\n \"declarationMap\": true,\n \"sourceMap\": true,\n \"outDir\": \"./dist\",\n \"rootDir\": \"./src\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"forceConsistentCasingInFileNames\": true,\n \"resolveJsonModule\": true\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\", \"dist\"]\n}\n",186 "mimeType": null,187 "size": null,188 "icons": null,189 "annotations": null,190 "meta": null191 },192 {193 "name": "package-lock.json",194 "title": null,195 "uri": "skill://package-lock.json",196 "description": "{\n \"name\": \"clawvault\",\n \"version\": \"1.4.2\",\n \"lockfileVersion\": 3,\n \"requires\": true,\n \"packages\": {\n \"\": {\n \"name\": \"clawvault\",\n \"version\": \"1.4.2\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"chalk\": \"^5.3.0\",\n \"commander\": \"^12.0.0\",\n \"glob\": \"^10.3.10\",\n \"gray-matter\": \"^4.0.3\",\n \"natural\": \"^6.10.4\",\n \"qmd\": \"github:tobi/qmd\"\n },\n \"bin\": {\n \"clawvault\": \"bin/clawvault.js\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.11.0\",\n \"tsup\": \"^8.0.1\",\n \"typescript\": \"^5.3.3\",\n \"vitest\": \"^1.2.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/aix-ppc64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz\",\n \"integrity\": \"sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"aix\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/android-arm\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz\",\n \"integrity\": \"sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/android-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/android-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/darwin-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/darwin-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/freebsd-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/freebsd-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-arm\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz\",\n \"integrity\": \"sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-ia32\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz\",\n \"integrity\": \"sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-loong64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz\",\n \"integrity\": \"sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==\",\n \"cpu\": [\n \"loong64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-mips64el\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz\",\n \"integrity\": \"sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==\",\n \"cpu\": [\n \"mips64el\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-ppc64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz\",\n \"integrity\": \"sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-riscv64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz\",\n \"integrity\": \"sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==\",\n \"cpu\": [\n \"riscv64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-s390x\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz\",\n \"integrity\": \"sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==\",\n \"cpu\": [\n \"s390x\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/linux-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/netbsd-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"netbsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/netbsd-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"netbsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/openbsd-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openbsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/openbsd-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openbsd\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/openharmony-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openharmony\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/sunos-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"sunos\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/win32-arm64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz\",\n \"integrity\": \"sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/win32-ia32\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz\",\n \"integrity\": \"sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@esbuild/win32-x64\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz\",\n \"integrity\": \"sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@hono/node-server\": {\n \"version\": \"1.19.9\",\n \"resolved\": \"https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz\",\n \"integrity\": \"sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18.14.1\"\n },\n \"peerDependencies\": {\n \"hono\": \"^4\"\n }\n },\n \"node_modules/@huggingface/jinja\": {\n \"version\": \"0.5.5\",\n \"resolved\": \"https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.5.tgz\",\n \"integrity\": \"sha512-xRlzazC+QZwr6z4ixEqYHo9fgwhTZ3xNSdljlKfUFGZSdlvt166DljRELFUfFytlYOYvo3vTisA/AFOuOAzFQQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/@isaacs/cliui\": {\n \"version\": \"8.0.2\",\n \"resolved\": \"https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz\",\n \"integrity\": \"sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"string-width\": \"^5.1.2\",\n \"string-width-cjs\": \"npm:string-width@^4.2.0\",\n \"strip-ansi\": \"^7.0.1\",\n \"strip-ansi-cjs\": \"npm:strip-ansi@^6.0.1\",\n \"wrap-ansi\": \"^8.1.0\",\n \"wrap-ansi-cjs\": \"npm:wrap-ansi@^7.0.0\"\n },\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/@jest/schemas\": {\n \"version\": \"29.6.3\",\n \"resolved\": \"https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz\",\n \"integrity\": \"sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@sinclair/typebox\": \"^0.27.8\"\n },\n \"engines\": {\n \"node\": \"^14.15.0 || ^16.10.0 || >=18.0.0\"\n }\n },\n \"node_modules/@jridgewell/gen-mapping\": {\n \"version\": \"0.3.13\",\n \"resolved\": \"https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz\",\n \"integrity\": \"sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jridgewell/sourcemap-codec\": \"^1.5.0\",\n \"@jridgewell/trace-mapping\": \"^0.3.24\"\n }\n },\n \"node_modules/@jridgewell/resolve-uri\": {\n \"version\": \"3.1.2\",\n \"resolved\": \"https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz\",\n \"integrity\": \"sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=6.0.0\"\n }\n },\n \"node_modules/@jridgewell/sourcemap-codec\": {\n \"version\": \"1.5.5\",\n \"resolved\": \"https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz\",\n \"integrity\": \"sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@jridgewell/trace-mapping\": {\n \"version\": \"0.3.31\",\n \"resolved\": \"https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz\",\n \"integrity\": \"sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jridgewell/resolve-uri\": \"^3.1.0\",\n \"@jridgewell/sourcemap-codec\": \"^1.4.14\"\n }\n },\n \"node_modules/@kwsites/file-exists\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz\",\n \"integrity\": \"sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"debug\": \"^4.1.1\"\n }\n },\n \"node_modules/@kwsites/promise-deferred\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz\",\n \"integrity\": \"sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/@modelcontextprotocol/sdk\": {\n \"version\": \"1.25.3\",\n \"resolved\": \"https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.3.tgz\",\n \"integrity\": \"sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@hono/node-server\": \"^1.19.9\",\n \"ajv\": \"^8.17.1\",\n \"ajv-formats\": \"^3.0.1\",\n \"content-type\": \"^1.0.5\",\n \"cors\": \"^2.8.5\",\n \"cross-spawn\": \"^7.0.5\",\n \"eventsource\": \"^3.0.2\",\n \"eventsource-parser\": \"^3.0.0\",\n \"express\": \"^5.0.1\",\n \"express-rate-limit\": \"^7.5.0\",\n \"jose\": \"^6.1.1\",\n \"json-schema-typed\": \"^8.0.2\",\n \"pkce-challenge\": \"^5.0.0\",\n \"raw-body\": \"^3.0.0\",\n \"zod\": \"^3.25 || ^4.0\",\n \"zod-to-json-schema\": \"^3.25.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"peerDependencies\": {\n \"@cfworker/json-schema\": \"^4.1.1\",\n \"zod\": \"^3.25 || ^4.0\"\n },\n \"peerDependenciesMeta\": {\n \"@cfworker/json-schema\": {\n \"optional\": true\n },\n \"zod\": {\n \"optional\": false\n }\n }\n },\n \"node_modules/@mongodb-js/saslprep\": {\n \"version\": \"1.4.5\",\n \"resolved\": \"https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.5.tgz\",\n \"integrity\": \"sha512-k64Lbyb7ycCSXHSLzxVdb2xsKGPMvYZfCICXvDsI8Z65CeWQzTEKS4YmGbnqw+U9RBvLPTsB6UCmwkgsDTGWIw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"sparse-bitfield\": \"^3.0.3\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-arm64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-arm64/-/linux-arm64-3.15.1.tgz\",\n \"integrity\": \"sha512-g7JC/WwDyyBSmkIjSvRF2XLW+YA0z2ZVBSAKSv106mIPO4CzC078woTuTaPsykWgIaKcQRyXuW5v5XQMcT1OOA==\",\n \"cpu\": [\n \"arm64\",\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-armv7l\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-armv7l/-/linux-armv7l-3.15.1.tgz\",\n \"integrity\": \"sha512-MSxR3A0vFSVWbmVSkNqNXQnI45L2Vg7/PRgJukcjChk7YzRxs9L+oQMeycVW3BsQ03mIZ0iORsZ9MNIBEbdS3g==\",\n \"cpu\": [\n \"arm\",\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-x64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-x64/-/linux-x64-3.15.1.tgz\",\n \"integrity\": \"sha512-w4SdxJaA9eJLVYWX+Jv48hTP4oO79BJQIFURMi7hXIFXbxyyOov/r6sVaQ1WiL83nVza37U5Qg4L9Gb/KRdNWQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-x64-cuda\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-x64-cuda/-/linux-x64-cuda-3.15.1.tgz\",\n \"integrity\": \"sha512-kngwoq1KdrqSr/b6+tn5jbtGHI0tZnW5wofKssZy+Il2ge3eN9FowKbXG4FH452g6qSSVoDccAoTvYOxyLyX+w==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-x64-cuda-ext\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-x64-cuda-ext/-/linux-x64-cuda-ext-3.15.1.tgz\",\n \"integrity\": \"sha512-toepvLcXjgaQE/QGIThHBD58jbHGBWT1jhblJkCjYBRHfVOO+6n/PmVsJt+yMfu5Z93A2gF8YOvVyZXNXmGo5g==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/linux-x64-vulkan\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/linux-x64-vulkan/-/linux-x64-vulkan-3.15.1.tgz\",\n \"integrity\": \"sha512-CMsyQkGKpHKeOH9+ZPxo0hO0usg8jabq5/aM3JwdX9CiuXhXUa3nu3NH4RObiNi596Zwn/zWzlps0HRwcpL8rw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/mac-arm64-metal\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/mac-arm64-metal/-/mac-arm64-metal-3.15.1.tgz\",\n \"integrity\": \"sha512-ePTweqohcy6Gjs1agXWy4FxAw5W4Avr7NeqqiFWJ5ngZ1U3ZXdruUHB8L/vDxyn3FzKvstrFyN7UScbi0pzXrA==\",\n \"cpu\": [\n \"arm64\",\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/mac-x64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/mac-x64/-/mac-x64-3.15.1.tgz\",\n \"integrity\": \"sha512-NAetSQONxpNXTBnEo7oOkKZ84wO2avBy6V9vV9ntjJLb/07g7Rar8s/jVaicc/rVl6C+8ljZNwqJeynirgAC5w==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-arm64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-arm64/-/win-arm64-3.15.1.tgz\",\n \"integrity\": \"sha512-1O9tNSUgvgLL5hqgEuYiz7jRdA3+9yqzNJyPW1jExlQo442OA0eIpHBmeOtvXLwMkY7qv7wE75FdOPR7NVEnvg==\",\n \"cpu\": [\n \"arm64\",\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-x64\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-x64/-/win-x64-3.15.1.tgz\",\n \"integrity\": \"sha512-jtoXBa6h+VPsQgefrO7HDjYv4WvxfHtUO30ABwCUDuEgM0e05YYhxMZj1z2Ns47UrquNvd/LUPCyjHKqHUN+5Q==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-x64-cuda\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-x64-cuda/-/win-x64-cuda-3.15.1.tgz\",\n \"integrity\": \"sha512-swoyx0/dY4ixiu3mEWrIAinx0ffHn9IncELDNREKG+iIXfx6w0OujOMQ6+X+lGj+sjE01yMUP/9fv6GEp2pmBw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-x64-cuda-ext\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-x64-cuda-ext/-/win-x64-cuda-ext-3.15.1.tgz\",\n \"integrity\": \"sha512-mO3Tf6D3UlFkjQF5J96ynTkjdF7dac/f5f61cEh6oU4D3hdx+cwnmBWT1gVhDSLboJYzCHtx7U2EKPP6n8HoWA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@node-llama-cpp/win-x64-vulkan\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/@node-llama-cpp/win-x64-vulkan/-/win-x64-vulkan-3.15.1.tgz\",\n \"integrity\": \"sha512-BPBjUEIkFTdcHSsQyblP0v/aPPypi6uqQIq27mo4A49CYjX22JDmk4ncdBLk6cru+UkvwEEe+F2RomjoMt32aQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n },\n \"node_modules/@octokit/app\": {\n \"version\": \"16.1.2\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/app/-/app-16.1.2.tgz\",\n \"integrity\": \"sha512-8j7sEpUYVj18dxvh0KWj6W/l6uAiVRBl1JBDVRqH1VHKAO/G5eRVl4yEoYACjakWers1DjUkcCHyJNQK47JqyQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-app\": \"^8.1.2\",\n \"@octokit/auth-unauthenticated\": \"^7.0.3\",\n \"@octokit/core\": \"^7.0.6\",\n \"@octokit/oauth-app\": \"^8.0.3\",\n \"@octokit/plugin-paginate-rest\": \"^14.0.0\",\n \"@octokit/types\": \"^16.0.0\",\n \"@octokit/webhooks\": \"^14.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-app\": {\n \"version\": \"8.2.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-app/-/auth-app-8.2.0.tgz\",\n \"integrity\": \"sha512-vVjdtQQwomrZ4V46B9LaCsxsySxGoHsyw6IYBov/TqJVROrlYdyNgw5q6tQbB7KZt53v1l1W53RiqTvpzL907g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-oauth-app\": \"^9.0.3\",\n \"@octokit/auth-oauth-user\": \"^6.0.2\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"toad-cache\": \"^3.7.0\",\n \"universal-github-app-jwt\": \"^2.2.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-oauth-app\": {\n \"version\": \"9.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-9.0.3.tgz\",\n \"integrity\": \"sha512-+yoFQquaF8OxJSxTb7rnytBIC2ZLbLqA/yb71I4ZXT9+Slw4TziV9j/kyGhUFRRTF2+7WlnIWsePZCWHs+OGjg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-oauth-device\": \"^8.0.3\",\n \"@octokit/auth-oauth-user\": \"^6.0.2\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-oauth-device\": {\n \"version\": \"8.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-8.0.3.tgz\",\n \"integrity\": \"sha512-zh2W0mKKMh/VWZhSqlaCzY7qFyrgd9oTWmTmHaXnHNeQRCZr/CXy2jCgHo4e4dJVTiuxP5dLa0YM5p5QVhJHbw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/oauth-methods\": \"^6.0.2\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-oauth-user\": {\n \"version\": \"6.0.2\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-6.0.2.tgz\",\n \"integrity\": \"sha512-qLoPPc6E6GJoz3XeDG/pnDhJpTkODTGG4kY0/Py154i/I003O9NazkrwJwRuzgCalhzyIeWQ+6MDvkUmKXjg/A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-oauth-device\": \"^8.0.3\",\n \"@octokit/oauth-methods\": \"^6.0.2\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-token\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz\",\n \"integrity\": \"sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/auth-unauthenticated\": {\n \"version\": \"7.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-7.0.3.tgz\",\n \"integrity\": \"sha512-8Jb1mtUdmBHL7lGmop9mU9ArMRUTRhg8vp0T1VtZ4yd9vEm3zcLwmjQkhNEduKawOOORie61xhtYIhTDN+ZQ3g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/core\": {\n \"version\": \"7.0.6\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz\",\n \"integrity\": \"sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-token\": \"^6.0.0\",\n \"@octokit/graphql\": \"^9.0.3\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"before-after-hook\": \"^4.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/endpoint\": {\n \"version\": \"11.0.2\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.2.tgz\",\n \"integrity\": \"sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.2\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/graphql\": {\n \"version\": \"9.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz\",\n \"integrity\": \"sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/types\": \"^16.0.0\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/oauth-app\": {\n \"version\": \"8.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-8.0.3.tgz\",\n \"integrity\": \"sha512-jnAjvTsPepyUaMu9e69hYBuozEPgYqP4Z3UnpmvoIzHDpf8EXDGvTY1l1jK0RsZ194oRd+k6Hm13oRU8EoDFwg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/auth-oauth-app\": \"^9.0.2\",\n \"@octokit/auth-oauth-user\": \"^6.0.1\",\n \"@octokit/auth-unauthenticated\": \"^7.0.2\",\n \"@octokit/core\": \"^7.0.5\",\n \"@octokit/oauth-authorization-url\": \"^8.0.0\",\n \"@octokit/oauth-methods\": \"^6.0.1\",\n \"@types/aws-lambda\": \"^8.10.83\",\n \"universal-user-agent\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/oauth-authorization-url\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-8.0.0.tgz\",\n \"integrity\": \"sha512-7QoLPRh/ssEA/HuHBHdVdSgF8xNLz/Bc5m9fZkArJE5bb6NmVkDm3anKxXPmN1zh6b5WKZPRr3697xKT/yM3qQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/oauth-methods\": {\n \"version\": \"6.0.2\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-6.0.2.tgz\",\n \"integrity\": \"sha512-HiNOO3MqLxlt5Da5bZbLV8Zarnphi4y9XehrbaFMkcoJ+FL7sMxH/UlUsCVxpddVu4qvNDrBdaTVE2o4ITK8ng==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/oauth-authorization-url\": \"^8.0.0\",\n \"@octokit/request\": \"^10.0.6\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/openapi-types\": {\n \"version\": \"27.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz\",\n \"integrity\": \"sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/@octokit/openapi-webhooks-types\": {\n \"version\": \"12.1.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-12.1.0.tgz\",\n \"integrity\": \"sha512-WiuzhOsiOvb7W3Pvmhf8d2C6qaLHXrWiLBP4nJ/4kydu+wpagV5Fkz9RfQwV2afYzv3PB+3xYgp4mAdNGjDprA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/@octokit/plugin-paginate-graphql\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-6.0.0.tgz\",\n \"integrity\": \"sha512-crfpnIoFiBtRkvPqOyLOsw12XsveYuY2ieP6uYDosoUegBJpSVxGwut9sxUgFFcll3VTOTqpUf8yGd8x1OmAkQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \">=6\"\n }\n },\n \"node_modules/@octokit/plugin-paginate-rest\": {\n \"version\": \"14.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz\",\n \"integrity\": \"sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \">=6\"\n }\n },\n \"node_modules/@octokit/plugin-rest-endpoint-methods\": {\n \"version\": \"17.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz\",\n \"integrity\": \"sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \">=6\"\n }\n },\n \"node_modules/@octokit/plugin-retry\": {\n \"version\": \"8.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-8.0.3.tgz\",\n \"integrity\": \"sha512-vKGx1i3MC0za53IzYBSBXcrhmd+daQDzuZfYDd52X5S0M2otf3kVZTVP8bLA3EkU0lTvd1WEC2OlNNa4G+dohA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"bottleneck\": \"^2.15.3\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \">=7\"\n }\n },\n \"node_modules/@octokit/plugin-throttling\": {\n \"version\": \"11.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-11.0.3.tgz\",\n \"integrity\": \"sha512-34eE0RkFCKycLl2D2kq7W+LovheM/ex3AwZCYN8udpi6bxsyjZidb2McXs69hZhLmJlDqTSP8cH+jSRpiaijBg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\",\n \"bottleneck\": \"^2.15.3\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n },\n \"peerDependencies\": {\n \"@octokit/core\": \"^7.0.0\"\n }\n },\n \"node_modules/@octokit/request\": {\n \"version\": \"10.0.7\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/request/-/request-10.0.7.tgz\",\n \"integrity\": \"sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/endpoint\": \"^11.0.2\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"fast-content-type-parse\": \"^3.0.0\",\n \"universal-user-agent\": \"^7.0.2\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/request-error\": {\n \"version\": \"7.1.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz\",\n \"integrity\": \"sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/types\": \"^16.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/types\": {\n \"version\": \"16.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz\",\n \"integrity\": \"sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/openapi-types\": \"^27.0.0\"\n }\n },\n \"node_modules/@octokit/webhooks\": {\n \"version\": \"14.2.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/webhooks/-/webhooks-14.2.0.tgz\",\n \"integrity\": \"sha512-da6KbdNCV5sr1/txD896V+6W0iamFWrvVl8cHkBSPT+YlvmT3DwXa4jxZnQc+gnuTEqSWbBeoSZYTayXH9wXcw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/openapi-webhooks-types\": \"12.1.0\",\n \"@octokit/request-error\": \"^7.0.0\",\n \"@octokit/webhooks-methods\": \"^6.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@octokit/webhooks-methods\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-6.0.0.tgz\",\n \"integrity\": \"sha512-MFlzzoDJVw/GcbfzVC1RLR36QqkTLUf79vLVO3D+xn7r0QgxnFoLZgtrzxiQErAjFUOdH6fas2KeQJ1yr/qaXQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/@pkgjs/parseargs\": {\n \"version\": \"0.11.0\",\n \"resolved\": \"https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz\",\n \"integrity\": \"sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=14\"\n }\n },\n \"node_modules/@redis/bloom\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz\",\n \"integrity\": \"sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@redis/client\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz\",\n \"integrity\": \"sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"cluster-key-slot\": \"1.1.2\",\n \"generic-pool\": \"3.9.0\",\n \"yallist\": \"4.0.0\"\n },\n \"engines\": {\n \"node\": \">=14\"\n }\n },\n \"node_modules/@redis/graph\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz\",\n \"integrity\": \"sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@redis/json\": {\n \"version\": \"1.0.7\",\n \"resolved\": \"https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz\",\n \"integrity\": \"sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@redis/search\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz\",\n \"integrity\": \"sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@redis/time-series\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz\",\n \"integrity\": \"sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@redis/client\": \"^1.0.0\"\n }\n },\n \"node_modules/@reflink/reflink\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink/-/reflink-0.1.19.tgz\",\n \"integrity\": \"sha512-DmCG8GzysnCZ15bres3N5AHCmwBwYgp0As6xjhQ47rAUTUXxJiK+lLUxaGsX3hd/30qUpVElh05PbGuxRPgJwA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 10\"\n },\n \"optionalDependencies\": {\n \"@reflink/reflink-darwin-arm64\": \"0.1.19\",\n \"@reflink/reflink-darwin-x64\": \"0.1.19\",\n \"@reflink/reflink-linux-arm64-gnu\": \"0.1.19\",\n \"@reflink/reflink-linux-arm64-musl\": \"0.1.19\",\n \"@reflink/reflink-linux-x64-gnu\": \"0.1.19\",\n \"@reflink/reflink-linux-x64-musl\": \"0.1.19\",\n \"@reflink/reflink-win32-arm64-msvc\": \"0.1.19\",\n \"@reflink/reflink-win32-x64-msvc\": \"0.1.19\"\n }\n },\n \"node_modules/@reflink/reflink-darwin-arm64\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-darwin-arm64/-/reflink-darwin-arm64-0.1.19.tgz\",\n \"integrity\": \"sha512-ruy44Lpepdk1FqDz38vExBY/PVUsjxZA+chd9wozjUH9JjuDT/HEaQYA6wYN9mf041l0yLVar6BCZuWABJvHSA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-darwin-x64\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-darwin-x64/-/reflink-darwin-x64-0.1.19.tgz\",\n \"integrity\": \"sha512-By85MSWrMZa+c26TcnAy8SDk0sTUkYlNnwknSchkhHpGXOtjNDUOxJE9oByBnGbeuIE1PiQsxDG3Ud+IVV9yuA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-linux-arm64-gnu\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-linux-arm64-gnu/-/reflink-linux-arm64-gnu-0.1.19.tgz\",\n \"integrity\": \"sha512-7P+er8+rP9iNeN+bfmccM4hTAaLP6PQJPKWSA4iSk2bNvo6KU6RyPgYeHxXmzNKzPVRcypZQTpFgstHam6maVg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-linux-arm64-musl\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-linux-arm64-musl/-/reflink-linux-arm64-musl-0.1.19.tgz\",\n \"integrity\": \"sha512-37iO/Dp6m5DDaC2sf3zPtx/hl9FV3Xze4xoYidrxxS9bgP3S8ALroxRK6xBG/1TtfXKTvolvp+IjrUU6ujIGmA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-linux-x64-gnu\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-linux-x64-gnu/-/reflink-linux-x64-gnu-0.1.19.tgz\",\n \"integrity\": \"sha512-jbI8jvuYCaA3MVUdu8vLoLAFqC+iNMpiSuLbxlAgg7x3K5bsS8nOpTRnkLF7vISJ+rVR8W+7ThXlXlUQ93ulkw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-linux-x64-musl\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-linux-x64-musl/-/reflink-linux-x64-musl-0.1.19.tgz\",\n \"integrity\": \"sha512-e9FBWDe+lv7QKAwtKOt6A2W/fyy/aEEfr0g6j/hWzvQcrzHCsz07BNQYlNOjTfeytrtLU7k449H1PI95jA4OjQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-win32-arm64-msvc\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-win32-arm64-msvc/-/reflink-win32-arm64-msvc-0.1.19.tgz\",\n \"integrity\": \"sha512-09PxnVIQcd+UOn4WAW73WU6PXL7DwGS6wPlkMhMg2zlHHG65F3vHepOw06HFCq+N42qkaNAc8AKIabWvtk6cIQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@reflink/reflink-win32-x64-msvc\": {\n \"version\": \"0.1.19\",\n \"resolved\": \"https://registry.npmjs.org/@reflink/reflink-win32-x64-msvc/-/reflink-win32-x64-msvc-0.1.19.tgz\",\n \"integrity\": \"sha512-E//yT4ni2SyhwP8JRjVGWr3cbnhWDiPLgnQ66qqaanjjnMiu3O/2tjCPQXlcGc/DEYofpDc9fvhv6tALQsMV9w==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">= 10\"\n }\n },\n \"node_modules/@rollup/rollup-android-arm-eabi\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz\",\n \"integrity\": \"sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ]\n },\n \"node_modules/@rollup/rollup-android-arm64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz\",\n \"integrity\": \"sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ]\n },\n \"node_modules/@rollup/rollup-darwin-arm64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz\",\n \"integrity\": \"sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ]\n },\n \"node_modules/@rollup/rollup-darwin-x64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz\",\n \"integrity\": \"sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ]\n },\n \"node_modules/@rollup/rollup-freebsd-arm64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz\",\n \"integrity\": \"sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ]\n },\n \"node_modules/@rollup/rollup-freebsd-x64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz\",\n \"integrity\": \"sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-arm-gnueabihf\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz\",\n \"integrity\": \"sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-arm-musleabihf\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz\",\n \"integrity\": \"sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-arm64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-arm64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-loong64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==\",\n \"cpu\": [\n \"loong64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-loong64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==\",\n \"cpu\": [\n \"loong64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-ppc64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-ppc64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-riscv64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==\",\n \"cpu\": [\n \"riscv64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-riscv64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==\",\n \"cpu\": [\n \"riscv64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-s390x-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==\",\n \"cpu\": [\n \"s390x\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-x64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-linux-x64-musl\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz\",\n \"integrity\": \"sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/@rollup/rollup-openbsd-x64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz\",\n \"integrity\": \"sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openbsd\"\n ]\n },\n \"node_modules/@rollup/rollup-openharmony-arm64\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz\",\n \"integrity\": \"sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openharmony\"\n ]\n },\n \"node_modules/@rollup/rollup-win32-arm64-msvc\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz\",\n \"integrity\": \"sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/@rollup/rollup-win32-ia32-msvc\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz\",\n \"integrity\": \"sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/@rollup/rollup-win32-x64-gnu\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz\",\n \"integrity\": \"sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/@rollup/rollup-win32-x64-msvc\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz\",\n \"integrity\": \"sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/@sinclair/typebox\": {\n \"version\": \"0.27.8\",\n \"resolved\": \"https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz\",\n \"integrity\": \"sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@tinyhttp/content-disposition\": {\n \"version\": \"2.2.4\",\n \"resolved\": \"https://registry.npmjs.org/@tinyhttp/content-disposition/-/content-disposition-2.2.4.tgz\",\n \"integrity\": \"sha512-5Kc5CM2Ysn3vTTArBs2vESUt0AQiWZA86yc1TI3B+lxXmtEq133C1nxXNOgnzhrivdPZIh3zLj5gDnZjoLL5GA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12.17.0\"\n },\n \"funding\": {\n \"type\": \"individual\",\n \"url\": \"https://github.com/tinyhttp/tinyhttp?sponsor=1\"\n }\n },\n \"node_modules/@types/aws-lambda\": {\n \"version\": \"8.10.160\",\n \"resolved\": \"https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.160.tgz\",\n \"integrity\": \"sha512-uoO4QVQNWFPJMh26pXtmtrRfGshPUSpMZGUyUQY20FhfHEElEBOPKgVmFs1z+kbpyBsRs2JnoOPT7++Z4GA9pA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/@types/estree\": {\n \"version\": \"1.0.8\",\n \"resolved\": \"https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz\",\n \"integrity\": \"sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@types/node\": {\n \"version\": \"20.19.30\",\n \"resolved\": \"https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz\",\n \"integrity\": \"sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"undici-types\": \"~6.21.0\"\n }\n },\n \"node_modules/@types/webidl-conversions\": {\n \"version\": \"7.0.3\",\n \"resolved\": \"https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz\",\n \"integrity\": \"sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==\",\n \"license\": \"MIT\"\n },\n \"node_modules/@types/whatwg-url\": {\n \"version\": \"11.0.5\",\n \"resolved\": \"https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz\",\n \"integrity\": \"sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@types/webidl-conversions\": \"*\"\n }\n },\n \"node_modules/@vitest/expect\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz\",\n \"integrity\": \"sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@vitest/spy\": \"1.6.1\",\n \"@vitest/utils\": \"1.6.1\",\n \"chai\": \"^4.3.10\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/@vitest/runner\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/runner/-/runner-1.6.1.tgz\",\n \"integrity\": \"sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@vitest/utils\": \"1.6.1\",\n \"p-limit\": \"^5.0.0\",\n \"pathe\": \"^1.1.1\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/@vitest/runner/node_modules/pathe\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz\",\n \"integrity\": \"sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@vitest/snapshot\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.1.tgz\",\n \"integrity\": \"sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"magic-string\": \"^0.30.5\",\n \"pathe\": \"^1.1.1\",\n \"pretty-format\": \"^29.7.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/@vitest/snapshot/node_modules/pathe\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz\",\n \"integrity\": \"sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/@vitest/spy\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/spy/-/spy-1.6.1.tgz\",\n \"integrity\": \"sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"tinyspy\": \"^2.2.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/@vitest/utils\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/@vitest/utils/-/utils-1.6.1.tgz\",\n \"integrity\": \"sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"diff-sequences\": \"^29.6.3\",\n \"estree-walker\": \"^3.0.3\",\n \"loupe\": \"^2.3.7\",\n \"pretty-format\": \"^29.7.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/accepts\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz\",\n \"integrity\": \"sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"mime-types\": \"^3.0.0\",\n \"negotiator\": \"^1.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/acorn\": {\n \"version\": \"8.15.0\",\n \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz\",\n \"integrity\": \"sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"bin\": {\n \"acorn\": \"bin/acorn\"\n },\n \"engines\": {\n \"node\": \">=0.4.0\"\n }\n },\n \"node_modules/acorn-walk\": {\n \"version\": \"8.3.4\",\n \"resolved\": \"https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz\",\n \"integrity\": \"sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"acorn\": \"^8.11.0\"\n },\n \"engines\": {\n \"node\": \">=0.4.0\"\n }\n },\n \"node_modules/afinn-165\": {\n \"version\": \"1.0.4\",\n \"resolved\": \"https://registry.npmjs.org/afinn-165/-/afinn-165-1.0.4.tgz\",\n \"integrity\": \"sha512-7+Wlx3BImrK0HiG6y3lU4xX7SpBPSSu8T9iguPMlaueRFxjbYwAQrp9lqZUuFikqKbd/en8lVREILvP2J80uJA==\",\n \"license\": \"MIT\",\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/wooorm\"\n }\n },\n \"node_modules/afinn-165-financialmarketnews\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/afinn-165-financialmarketnews/-/afinn-165-financialmarketnews-3.0.0.tgz\",\n \"integrity\": \"sha512-0g9A1S3ZomFIGDTzZ0t6xmv4AuokBvBmpes8htiyHpH7N4xDmvSQL6UxL/Zcs2ypRb3VwgCscaD8Q3zEawKYhw==\",\n \"license\": \"MIT\",\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/wooorm\"\n }\n },\n \"node_modules/ajv\": {\n \"version\": \"8.17.1\",\n \"resolved\": \"https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz\",\n \"integrity\": \"sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"fast-deep-equal\": \"^3.1.3\",\n \"fast-uri\": \"^3.0.1\",\n \"json-schema-traverse\": \"^1.0.0\",\n \"require-from-string\": \"^2.0.2\"\n },\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/epoberezkin\"\n }\n },\n \"node_modules/ajv-formats\": {\n \"version\": \"3.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz\",\n \"integrity\": \"sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ajv\": \"^8.0.0\"\n },\n \"peerDependencies\": {\n \"ajv\": \"^8.0.0\"\n },\n \"peerDependenciesMeta\": {\n \"ajv\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/ansi-escapes\": {\n \"version\": \"6.2.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz\",\n \"integrity\": \"sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=14.16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ansi-regex\": {\n \"version\": \"6.2.2\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz\",\n \"integrity\": \"sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-regex?sponsor=1\"\n }\n },\n \"node_modules/ansi-styles\": {\n \"version\": \"5.2.0\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz\",\n \"integrity\": \"sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=10\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/any-promise\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz\",\n \"integrity\": \"sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/apparatus\": {\n \"version\": \"0.0.10\",\n \"resolved\": \"https://registry.npmjs.org/apparatus/-/apparatus-0.0.10.tgz\",\n \"integrity\": \"sha512-KLy/ugo33KZA7nugtQ7O0E1c8kQ52N3IvD/XgIh4w/Nr28ypfkwDfA67F1ev4N1m5D+BOk1+b2dEJDfpj/VvZg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"sylvester\": \">= 0.0.8\"\n },\n \"engines\": {\n \"node\": \">=0.2.6\"\n }\n },\n \"node_modules/aproba\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz\",\n \"integrity\": \"sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/are-we-there-yet\": {\n \"version\": \"3.0.1\",\n \"resolved\": \"https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz\",\n \"integrity\": \"sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==\",\n \"deprecated\": \"This package is no longer supported.\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"delegates\": \"^1.0.0\",\n \"readable-stream\": \"^3.6.0\"\n },\n \"engines\": {\n \"node\": \"^12.13.0 || ^14.15.0 || >=16.0.0\"\n }\n },\n \"node_modules/argparse\": {\n \"version\": \"1.0.10\",\n \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz\",\n \"integrity\": \"sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"sprintf-js\": \"~1.0.2\"\n }\n },\n \"node_modules/assertion-error\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz\",\n \"integrity\": \"sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"*\"\n }\n },\n \"node_modules/async-retry\": {\n \"version\": \"1.3.3\",\n \"resolved\": \"https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz\",\n \"integrity\": \"sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"retry\": \"0.13.1\"\n }\n },\n \"node_modules/asynckit\": {\n \"version\": \"0.4.0\",\n \"resolved\": \"https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz\",\n \"integrity\": \"sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/axios\": {\n \"version\": \"1.13.4\",\n \"resolved\": \"https://registry.npmjs.org/axios/-/axios-1.13.4.tgz\",\n \"integrity\": \"sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"follow-redirects\": \"^1.15.6\",\n \"form-data\": \"^4.0.4\",\n \"proxy-from-env\": \"^1.1.0\"\n }\n },\n \"node_modules/balanced-match\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz\",\n \"integrity\": \"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==\",\n \"license\": \"MIT\"\n },\n \"node_modules/before-after-hook\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz\",\n \"integrity\": \"sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==\",\n \"license\": \"Apache-2.0\",\n \"optional\": true\n },\n \"node_modules/body-parser\": {\n \"version\": \"2.2.2\",\n \"resolved\": \"https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz\",\n \"integrity\": \"sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"bytes\": \"^3.1.2\",\n \"content-type\": \"^1.0.5\",\n \"debug\": \"^4.4.3\",\n \"http-errors\": \"^2.0.0\",\n \"iconv-lite\": \"^0.7.0\",\n \"on-finished\": \"^2.4.1\",\n \"qs\": \"^6.14.1\",\n \"raw-body\": \"^3.0.1\",\n \"type-is\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/bottleneck\": {\n \"version\": \"2.19.5\",\n \"resolved\": \"https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz\",\n \"integrity\": \"sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/brace-expansion\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz\",\n \"integrity\": \"sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"balanced-match\": \"^1.0.0\"\n }\n },\n \"node_modules/bson\": {\n \"version\": \"6.10.4\",\n \"resolved\": \"https://registry.npmjs.org/bson/-/bson-6.10.4.tgz\",\n \"integrity\": \"sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==\",\n \"license\": \"Apache-2.0\",\n \"engines\": {\n \"node\": \">=16.20.1\"\n }\n },\n \"node_modules/bundle-require\": {\n \"version\": \"5.1.0\",\n \"resolved\": \"https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz\",\n \"integrity\": \"sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"load-tsconfig\": \"^0.2.3\"\n },\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n },\n \"peerDependencies\": {\n \"esbuild\": \">=0.18\"\n }\n },\n \"node_modules/bytes\": {\n \"version\": \"3.1.2\",\n \"resolved\": \"https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz\",\n \"integrity\": \"sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/cac\": {\n \"version\": \"6.7.14\",\n \"resolved\": \"https://registry.npmjs.org/cac/-/cac-6.7.14.tgz\",\n \"integrity\": \"sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/call-bind-apply-helpers\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz\",\n \"integrity\": \"sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\",\n \"function-bind\": \"^1.1.2\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/call-bound\": {\n \"version\": \"1.0.4\",\n \"resolved\": \"https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz\",\n \"integrity\": \"sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bind-apply-helpers\": \"^1.0.2\",\n \"get-intrinsic\": \"^1.3.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/chai\": {\n \"version\": \"4.5.0\",\n \"resolved\": \"https://registry.npmjs.org/chai/-/chai-4.5.0.tgz\",\n \"integrity\": \"sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"assertion-error\": \"^1.1.0\",\n \"check-error\": \"^1.0.3\",\n \"deep-eql\": \"^4.1.3\",\n \"get-func-name\": \"^2.0.2\",\n \"loupe\": \"^2.3.6\",\n \"pathval\": \"^1.1.1\",\n \"type-detect\": \"^4.1.0\"\n },\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/chalk\": {\n \"version\": \"5.6.2\",\n \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz\",\n \"integrity\": \"sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^12.17.0 || ^14.13 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/chalk?sponsor=1\"\n }\n },\n \"node_modules/check-error\": {\n \"version\": \"1.0.3\",\n \"resolved\": \"https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz\",\n \"integrity\": \"sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"get-func-name\": \"^2.0.2\"\n },\n \"engines\": {\n \"node\": \"*\"\n }\n },\n \"node_modules/chmodrp\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/chmodrp/-/chmodrp-1.0.2.tgz\",\n \"integrity\": \"sha512-TdngOlFV1FLTzU0o1w8MB6/BFywhtLC0SzRTGJU7T9lmdjlCWeMRt1iVo0Ki+ldwNk0BqNiKoc8xpLZEQ8mY1w==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/chokidar\": {\n \"version\": \"4.0.3\",\n \"resolved\": \"https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz\",\n \"integrity\": \"sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"readdirp\": \"^4.0.1\"\n },\n \"engines\": {\n \"node\": \">= 14.16.0\"\n },\n \"funding\": {\n \"url\": \"https://paulmillr.com/funding/\"\n }\n },\n \"node_modules/chownr\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz\",\n \"integrity\": \"sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/ci-info\": {\n \"version\": \"4.4.0\",\n \"resolved\": \"https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz\",\n \"integrity\": \"sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/sibiraj-s\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/cli-cursor\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz\",\n \"integrity\": \"sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"restore-cursor\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/cli-spinners\": {\n \"version\": \"2.9.2\",\n \"resolved\": \"https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz\",\n \"integrity\": \"sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=6\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/cliui\": {\n \"version\": \"8.0.1\",\n \"resolved\": \"https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz\",\n \"integrity\": \"sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"string-width\": \"^4.2.0\",\n \"strip-ansi\": \"^6.0.1\",\n \"wrap-ansi\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/cliui/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/cliui/node_modules/ansi-styles\": {\n \"version\": \"4.3.0\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz\",\n \"integrity\": \"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"color-convert\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/cliui/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/cliui/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/cliui/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/cliui/node_modules/wrap-ansi\": {\n \"version\": \"7.0.0\",\n \"resolved\": \"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz\",\n \"integrity\": \"sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-styles\": \"^4.0.0\",\n \"string-width\": \"^4.1.0\",\n \"strip-ansi\": \"^6.0.0\"\n },\n \"engines\": {\n \"node\": \">=10\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/wrap-ansi?sponsor=1\"\n }\n },\n \"node_modules/cluster-key-slot\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz\",\n \"integrity\": \"sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==\",\n \"license\": \"Apache-2.0\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/cmake-js\": {\n \"version\": \"7.4.0\",\n \"resolved\": \"https://registry.npmjs.org/cmake-js/-/cmake-js-7.4.0.tgz\",\n \"integrity\": \"sha512-Lw0JxEHrmk+qNj1n9W9d4IvkDdYTBn7l2BW6XmtLj7WPpIo2shvxUy+YokfjMxAAOELNonQwX3stkPhM5xSC2Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"axios\": \"^1.6.5\",\n \"debug\": \"^4\",\n \"fs-extra\": \"^11.2.0\",\n \"memory-stream\": \"^1.0.0\",\n \"node-api-headers\": \"^1.1.0\",\n \"npmlog\": \"^6.0.2\",\n \"rc\": \"^1.2.7\",\n \"semver\": \"^7.5.4\",\n \"tar\": \"^6.2.0\",\n \"url-join\": \"^4.0.1\",\n \"which\": \"^2.0.2\",\n \"yargs\": \"^17.7.2\"\n },\n \"bin\": {\n \"cmake-js\": \"bin/cmake-js\"\n },\n \"engines\": {\n \"node\": \">= 14.15.0\"\n }\n },\n \"node_modules/color-convert\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz\",\n \"integrity\": \"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"color-name\": \"~1.1.4\"\n },\n \"engines\": {\n \"node\": \">=7.0.0\"\n }\n },\n \"node_modules/color-name\": {\n \"version\": \"1.1.4\",\n \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz\",\n \"integrity\": \"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==\",\n \"license\": \"MIT\"\n },\n \"node_modules/color-support\": {\n \"version\": \"1.1.3\",\n \"resolved\": \"https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz\",\n \"integrity\": \"sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"bin\": {\n \"color-support\": \"bin.js\"\n }\n },\n \"node_modules/combined-stream\": {\n \"version\": \"1.0.8\",\n \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz\",\n \"integrity\": \"sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"delayed-stream\": \"~1.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/commander\": {\n \"version\": \"12.1.0\",\n \"resolved\": \"https://registry.npmjs.org/commander/-/commander-12.1.0.tgz\",\n \"integrity\": \"sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/confbox\": {\n \"version\": \"0.1.8\",\n \"resolved\": \"https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz\",\n \"integrity\": \"sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/consola\": {\n \"version\": \"3.4.2\",\n \"resolved\": \"https://registry.npmjs.org/consola/-/consola-3.4.2.tgz\",\n \"integrity\": \"sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^14.18.0 || >=16.10.0\"\n }\n },\n \"node_modules/console-control-strings\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz\",\n \"integrity\": \"sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/content-disposition\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz\",\n \"integrity\": \"sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/content-type\": {\n \"version\": \"1.0.5\",\n \"resolved\": \"https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz\",\n \"integrity\": \"sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/cookie\": {\n \"version\": \"0.7.2\",\n \"resolved\": \"https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz\",\n \"integrity\": \"sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/cookie-signature\": {\n \"version\": \"1.2.2\",\n \"resolved\": \"https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz\",\n \"integrity\": \"sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=6.6.0\"\n }\n },\n \"node_modules/cors\": {\n \"version\": \"2.8.6\",\n \"resolved\": \"https://registry.npmjs.org/cors/-/cors-2.8.6.tgz\",\n \"integrity\": \"sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"object-assign\": \"^4\",\n \"vary\": \"^1\"\n },\n \"engines\": {\n \"node\": \">= 0.10\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/cross-spawn\": {\n \"version\": \"7.0.6\",\n \"resolved\": \"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz\",\n \"integrity\": \"sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"path-key\": \"^3.1.0\",\n \"shebang-command\": \"^2.0.0\",\n \"which\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">= 8\"\n }\n },\n \"node_modules/debug\": {\n \"version\": \"4.4.3\",\n \"resolved\": \"https://registry.npmjs.org/debug/-/debug-4.4.3.tgz\",\n \"integrity\": \"sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ms\": \"^2.1.3\"\n },\n \"engines\": {\n \"node\": \">=6.0\"\n },\n \"peerDependenciesMeta\": {\n \"supports-color\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/deep-eql\": {\n \"version\": \"4.1.4\",\n \"resolved\": \"https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz\",\n \"integrity\": \"sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"type-detect\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=6\"\n }\n },\n \"node_modules/deep-extend\": {\n \"version\": \"0.6.0\",\n \"resolved\": \"https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz\",\n \"integrity\": \"sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=4.0.0\"\n }\n },\n \"node_modules/delayed-stream\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\",\n \"integrity\": \"sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.4.0\"\n }\n },\n \"node_modules/delegates\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz\",\n \"integrity\": \"sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/depd\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/depd/-/depd-2.0.0.tgz\",\n \"integrity\": \"sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/diff-sequences\": {\n \"version\": \"29.6.3\",\n \"resolved\": \"https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz\",\n \"integrity\": \"sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^14.15.0 || ^16.10.0 || >=18.0.0\"\n }\n },\n \"node_modules/dotenv\": {\n \"version\": \"16.6.1\",\n \"resolved\": \"https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz\",\n \"integrity\": \"sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==\",\n \"license\": \"BSD-2-Clause\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://dotenvx.com\"\n }\n },\n \"node_modules/dunder-proto\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz\",\n \"integrity\": \"sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bind-apply-helpers\": \"^1.0.1\",\n \"es-errors\": \"^1.3.0\",\n \"gopd\": \"^1.2.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/eastasianwidth\": {\n \"version\": \"0.2.0\",\n \"resolved\": \"https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz\",\n \"integrity\": \"sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==\",\n \"license\": \"MIT\"\n },\n \"node_modules/ee-first\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\",\n \"integrity\": \"sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/emoji-regex\": {\n \"version\": \"9.2.2\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz\",\n \"integrity\": \"sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==\",\n \"license\": \"MIT\"\n },\n \"node_modules/encodeurl\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz\",\n \"integrity\": \"sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/env-var\": {\n \"version\": \"7.5.0\",\n \"resolved\": \"https://registry.npmjs.org/env-var/-/env-var-7.5.0.tgz\",\n \"integrity\": \"sha512-mKZOzLRN0ETzau2W2QXefbFjo5EF4yWq28OyKb9ICdeNhHJlOE/pHHnz4hdYJ9cNZXcJHo5xN4OT4pzuSHSNvA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/es-define-property\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz\",\n \"integrity\": \"sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/es-errors\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz\",\n \"integrity\": \"sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/es-object-atoms\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz\",\n \"integrity\": \"sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/es-set-tostringtag\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz\",\n \"integrity\": \"sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\",\n \"get-intrinsic\": \"^1.2.6\",\n \"has-tostringtag\": \"^1.0.2\",\n \"hasown\": \"^2.0.2\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/esbuild\": {\n \"version\": \"0.27.2\",\n \"resolved\": \"https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz\",\n \"integrity\": \"sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==\",\n \"dev\": true,\n \"hasInstallScript\": true,\n \"license\": \"MIT\",\n \"bin\": {\n \"esbuild\": \"bin/esbuild\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"optionalDependencies\": {\n \"@esbuild/aix-ppc64\": \"0.27.2\",\n \"@esbuild/android-arm\": \"0.27.2\",\n \"@esbuild/android-arm64\": \"0.27.2\",\n \"@esbuild/android-x64\": \"0.27.2\",\n \"@esbuild/darwin-arm64\": \"0.27.2\",\n \"@esbuild/darwin-x64\": \"0.27.2\",\n \"@esbuild/freebsd-arm64\": \"0.27.2\",\n \"@esbuild/freebsd-x64\": \"0.27.2\",\n \"@esbuild/linux-arm\": \"0.27.2\",\n \"@esbuild/linux-arm64\": \"0.27.2\",\n \"@esbuild/linux-ia32\": \"0.27.2\",\n \"@esbuild/linux-loong64\": \"0.27.2\",\n \"@esbuild/linux-mips64el\": \"0.27.2\",\n \"@esbuild/linux-ppc64\": \"0.27.2\",\n \"@esbuild/linux-riscv64\": \"0.27.2\",\n \"@esbuild/linux-s390x\": \"0.27.2\",\n \"@esbuild/linux-x64\": \"0.27.2\",\n \"@esbuild/netbsd-arm64\": \"0.27.2\",\n \"@esbuild/netbsd-x64\": \"0.27.2\",\n \"@esbuild/openbsd-arm64\": \"0.27.2\",\n \"@esbuild/openbsd-x64\": \"0.27.2\",\n \"@esbuild/openharmony-arm64\": \"0.27.2\",\n \"@esbuild/sunos-x64\": \"0.27.2\",\n \"@esbuild/win32-arm64\": \"0.27.2\",\n \"@esbuild/win32-ia32\": \"0.27.2\",\n \"@esbuild/win32-x64\": \"0.27.2\"\n }\n },\n \"node_modules/escalade\": {\n \"version\": \"3.2.0\",\n \"resolved\": \"https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz\",\n \"integrity\": \"sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=6\"\n }\n },\n \"node_modules/escape-html\": {\n \"version\": \"1.0.3\",\n \"resolved\": \"https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz\",\n \"integrity\": \"sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/esprima\": {\n \"version\": \"4.0.1\",\n \"resolved\": \"https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz\",\n \"integrity\": \"sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==\",\n \"license\": \"BSD-2-Clause\",\n \"bin\": {\n \"esparse\": \"bin/esparse.js\",\n \"esvalidate\": \"bin/esvalidate.js\"\n },\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/estree-walker\": {\n \"version\": \"3.0.3\",\n \"resolved\": \"https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz\",\n \"integrity\": \"sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@types/estree\": \"^1.0.0\"\n }\n },\n \"node_modules/etag\": {\n \"version\": \"1.8.1\",\n \"resolved\": \"https://registry.npmjs.org/etag/-/etag-1.8.1.tgz\",\n \"integrity\": \"sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/eventemitter3\": {\n \"version\": \"5.0.4\",\n \"resolved\": \"https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz\",\n \"integrity\": \"sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/eventsource\": {\n \"version\": \"3.0.7\",\n \"resolved\": \"https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz\",\n \"integrity\": \"sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"eventsource-parser\": \"^3.0.1\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n },\n \"node_modules/eventsource-parser\": {\n \"version\": \"3.0.6\",\n \"resolved\": \"https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz\",\n \"integrity\": \"sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n },\n \"node_modules/execa\": {\n \"version\": \"8.0.1\",\n \"resolved\": \"https://registry.npmjs.org/execa/-/execa-8.0.1.tgz\",\n \"integrity\": \"sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"cross-spawn\": \"^7.0.3\",\n \"get-stream\": \"^8.0.1\",\n \"human-signals\": \"^5.0.0\",\n \"is-stream\": \"^3.0.0\",\n \"merge-stream\": \"^2.0.0\",\n \"npm-run-path\": \"^5.1.0\",\n \"onetime\": \"^6.0.0\",\n \"signal-exit\": \"^4.1.0\",\n \"strip-final-newline\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">=16.17\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sindresorhus/execa?sponsor=1\"\n }\n },\n \"node_modules/express\": {\n \"version\": \"5.2.1\",\n \"resolved\": \"https://registry.npmjs.org/express/-/express-5.2.1.tgz\",\n \"integrity\": \"sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"accepts\": \"^2.0.0\",\n \"body-parser\": \"^2.2.1\",\n \"content-disposition\": \"^1.0.0\",\n \"content-type\": \"^1.0.5\",\n \"cookie\": \"^0.7.1\",\n \"cookie-signature\": \"^1.2.1\",\n \"debug\": \"^4.4.0\",\n \"depd\": \"^2.0.0\",\n \"encodeurl\": \"^2.0.0\",\n \"escape-html\": \"^1.0.3\",\n \"etag\": \"^1.8.1\",\n \"finalhandler\": \"^2.1.0\",\n \"fresh\": \"^2.0.0\",\n \"http-errors\": \"^2.0.0\",\n \"merge-descriptors\": \"^2.0.0\",\n \"mime-types\": \"^3.0.0\",\n \"on-finished\": \"^2.4.1\",\n \"once\": \"^1.4.0\",\n \"parseurl\": \"^1.3.3\",\n \"proxy-addr\": \"^2.0.7\",\n \"qs\": \"^6.14.0\",\n \"range-parser\": \"^1.2.1\",\n \"router\": \"^2.2.0\",\n \"send\": \"^1.1.0\",\n \"serve-static\": \"^2.2.0\",\n \"statuses\": \"^2.0.1\",\n \"type-is\": \"^2.0.1\",\n \"vary\": \"^1.1.2\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/express-rate-limit\": {\n \"version\": \"7.5.1\",\n \"resolved\": \"https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz\",\n \"integrity\": \"sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/express-rate-limit\"\n },\n \"peerDependencies\": {\n \"express\": \">= 4.11\"\n }\n },\n \"node_modules/extend-shallow\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz\",\n \"integrity\": \"sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"is-extendable\": \"^0.1.0\"\n },\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/fast-content-type-parse\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz\",\n \"integrity\": \"sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/fastify\"\n },\n {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/fastify\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/fast-deep-equal\": {\n \"version\": \"3.1.3\",\n \"resolved\": \"https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz\",\n \"integrity\": \"sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/fast-uri\": {\n \"version\": \"3.1.0\",\n \"resolved\": \"https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz\",\n \"integrity\": \"sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/fastify\"\n },\n {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/fastify\"\n }\n ],\n \"license\": \"BSD-3-Clause\",\n \"optional\": true\n },\n \"node_modules/fdir\": {\n \"version\": \"6.5.0\",\n \"resolved\": \"https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz\",\n \"integrity\": \"sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12.0.0\"\n },\n \"peerDependencies\": {\n \"picomatch\": \"^3 || ^4\"\n },\n \"peerDependenciesMeta\": {\n \"picomatch\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/filename-reserved-regex\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz\",\n \"integrity\": \"sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/filenamify\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz\",\n \"integrity\": \"sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"filename-reserved-regex\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">=16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/finalhandler\": {\n \"version\": \"2.1.1\",\n \"resolved\": \"https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz\",\n \"integrity\": \"sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"debug\": \"^4.4.0\",\n \"encodeurl\": \"^2.0.0\",\n \"escape-html\": \"^1.0.3\",\n \"on-finished\": \"^2.4.1\",\n \"parseurl\": \"^1.3.3\",\n \"statuses\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">= 18.0.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/fix-dts-default-cjs-exports\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz\",\n \"integrity\": \"sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"magic-string\": \"^0.30.17\",\n \"mlly\": \"^1.7.4\",\n \"rollup\": \"^4.34.8\"\n }\n },\n \"node_modules/follow-redirects\": {\n \"version\": \"1.15.11\",\n \"resolved\": \"https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz\",\n \"integrity\": \"sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==\",\n \"funding\": [\n {\n \"type\": \"individual\",\n \"url\": \"https://github.com/sponsors/RubenVerborgh\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=4.0\"\n },\n \"peerDependenciesMeta\": {\n \"debug\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/foreground-child\": {\n \"version\": \"3.3.1\",\n \"resolved\": \"https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz\",\n \"integrity\": \"sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"cross-spawn\": \"^7.0.6\",\n \"signal-exit\": \"^4.0.1\"\n },\n \"engines\": {\n \"node\": \">=14\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/form-data\": {\n \"version\": \"4.0.5\",\n \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz\",\n \"integrity\": \"sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"asynckit\": \"^0.4.0\",\n \"combined-stream\": \"^1.0.8\",\n \"es-set-tostringtag\": \"^2.1.0\",\n \"hasown\": \"^2.0.2\",\n \"mime-types\": \"^2.1.12\"\n },\n \"engines\": {\n \"node\": \">= 6\"\n }\n },\n \"node_modules/form-data/node_modules/mime-db\": {\n \"version\": \"1.52.0\",\n \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz\",\n \"integrity\": \"sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/form-data/node_modules/mime-types\": {\n \"version\": \"2.1.35\",\n \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz\",\n \"integrity\": \"sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"mime-db\": \"1.52.0\"\n },\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/forwarded\": {\n \"version\": \"0.2.0\",\n \"resolved\": \"https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz\",\n \"integrity\": \"sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/fresh\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz\",\n \"integrity\": \"sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/fs-extra\": {\n \"version\": \"11.3.3\",\n \"resolved\": \"https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz\",\n \"integrity\": \"sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"graceful-fs\": \"^4.2.0\",\n \"jsonfile\": \"^6.0.1\",\n \"universalify\": \"^2.0.0\"\n },\n \"engines\": {\n \"node\": \">=14.14\"\n }\n },\n \"node_modules/fs-minipass\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz\",\n \"integrity\": \"sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"minipass\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">= 8\"\n }\n },\n \"node_modules/fs-minipass/node_modules/minipass\": {\n \"version\": \"3.3.6\",\n \"resolved\": \"https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz\",\n \"integrity\": \"sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"yallist\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/fsevents\": {\n \"version\": \"2.3.3\",\n \"resolved\": \"https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz\",\n \"integrity\": \"sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==\",\n \"dev\": true,\n \"hasInstallScript\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \"^8.16.0 || ^10.6.0 || >=11.0.0\"\n }\n },\n \"node_modules/function-bind\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz\",\n \"integrity\": \"sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/gauge\": {\n \"version\": \"4.0.4\",\n \"resolved\": \"https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz\",\n \"integrity\": \"sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==\",\n \"deprecated\": \"This package is no longer supported.\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"aproba\": \"^1.0.3 || ^2.0.0\",\n \"color-support\": \"^1.1.3\",\n \"console-control-strings\": \"^1.1.0\",\n \"has-unicode\": \"^2.0.1\",\n \"signal-exit\": \"^3.0.7\",\n \"string-width\": \"^4.2.3\",\n \"strip-ansi\": \"^6.0.1\",\n \"wide-align\": \"^1.1.5\"\n },\n \"engines\": {\n \"node\": \"^12.13.0 || ^14.15.0 || >=16.0.0\"\n }\n },\n \"node_modules/gauge/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/gauge/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/gauge/node_modules/signal-exit\": {\n \"version\": \"3.0.7\",\n \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz\",\n \"integrity\": \"sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/gauge/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/gauge/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/generic-pool\": {\n \"version\": \"3.9.0\",\n \"resolved\": \"https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz\",\n \"integrity\": \"sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">= 4\"\n }\n },\n \"node_modules/get-caller-file\": {\n \"version\": \"2.0.5\",\n \"resolved\": \"https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz\",\n \"integrity\": \"sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"6.* || 8.* || >= 10.*\"\n }\n },\n \"node_modules/get-east-asian-width\": {\n \"version\": \"1.4.0\",\n \"resolved\": \"https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz\",\n \"integrity\": \"sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/get-func-name\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz\",\n \"integrity\": \"sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"*\"\n }\n },\n \"node_modules/get-intrinsic\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz\",\n \"integrity\": \"sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bind-apply-helpers\": \"^1.0.2\",\n \"es-define-property\": \"^1.0.1\",\n \"es-errors\": \"^1.3.0\",\n \"es-object-atoms\": \"^1.1.1\",\n \"function-bind\": \"^1.1.2\",\n \"get-proto\": \"^1.0.1\",\n \"gopd\": \"^1.2.0\",\n \"has-symbols\": \"^1.1.0\",\n \"hasown\": \"^2.0.2\",\n \"math-intrinsics\": \"^1.1.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/get-proto\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz\",\n \"integrity\": \"sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"dunder-proto\": \"^1.0.1\",\n \"es-object-atoms\": \"^1.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/get-stream\": {\n \"version\": \"8.0.1\",\n \"resolved\": \"https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz\",\n \"integrity\": \"sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/glob\": {\n \"version\": \"10.5.0\",\n \"resolved\": \"https://registry.npmjs.org/glob/-/glob-10.5.0.tgz\",\n \"integrity\": \"sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"foreground-child\": \"^3.1.0\",\n \"jackspeak\": \"^3.1.2\",\n \"minimatch\": \"^9.0.4\",\n \"minipass\": \"^7.1.2\",\n \"package-json-from-dist\": \"^1.0.0\",\n \"path-scurry\": \"^1.11.1\"\n },\n \"bin\": {\n \"glob\": \"dist/esm/bin.mjs\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/gopd\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz\",\n \"integrity\": \"sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/graceful-fs\": {\n \"version\": \"4.2.11\",\n \"resolved\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz\",\n \"integrity\": \"sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/gray-matter\": {\n \"version\": \"4.0.3\",\n \"resolved\": \"https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz\",\n \"integrity\": \"sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"js-yaml\": \"^3.13.1\",\n \"kind-of\": \"^6.0.2\",\n \"section-matter\": \"^1.0.0\",\n \"strip-bom-string\": \"^1.0.0\"\n },\n \"engines\": {\n \"node\": \">=6.0\"\n }\n },\n \"node_modules/has-symbols\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz\",\n \"integrity\": \"sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/has-tostringtag\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz\",\n \"integrity\": \"sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"has-symbols\": \"^1.0.3\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/has-unicode\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz\",\n \"integrity\": \"sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/hasown\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz\",\n \"integrity\": \"sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"function-bind\": \"^1.1.2\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/hono\": {\n \"version\": \"4.11.7\",\n \"resolved\": \"https://registry.npmjs.org/hono/-/hono-4.11.7.tgz\",\n \"integrity\": \"sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"peer\": true,\n \"engines\": {\n \"node\": \">=16.9.0\"\n }\n },\n \"node_modules/http-errors\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz\",\n \"integrity\": \"sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"depd\": \"~2.0.0\",\n \"inherits\": \"~2.0.4\",\n \"setprototypeof\": \"~1.2.0\",\n \"statuses\": \"~2.0.2\",\n \"toidentifier\": \"~1.0.1\"\n },\n \"engines\": {\n \"node\": \">= 0.8\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/human-signals\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz\",\n \"integrity\": \"sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==\",\n \"dev\": true,\n \"license\": \"Apache-2.0\",\n \"engines\": {\n \"node\": \">=16.17.0\"\n }\n },\n \"node_modules/iconv-lite\": {\n \"version\": \"0.7.2\",\n \"resolved\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz\",\n \"integrity\": \"sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"safer-buffer\": \">= 2.1.2 < 3.0.0\"\n },\n \"engines\": {\n \"node\": \">=0.10.0\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/ignore\": {\n \"version\": \"7.0.5\",\n \"resolved\": \"https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz\",\n \"integrity\": \"sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 4\"\n }\n },\n \"node_modules/inherits\": {\n \"version\": \"2.0.4\",\n \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz\",\n \"integrity\": \"sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/ini\": {\n \"version\": \"1.3.8\",\n \"resolved\": \"https://registry.npmjs.org/ini/-/ini-1.3.8.tgz\",\n \"integrity\": \"sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/ipaddr.js\": {\n \"version\": \"1.9.1\",\n \"resolved\": \"https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz\",\n \"integrity\": \"sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.10\"\n }\n },\n \"node_modules/ipull\": {\n \"version\": \"3.9.3\",\n \"resolved\": \"https://registry.npmjs.org/ipull/-/ipull-3.9.3.tgz\",\n \"integrity\": \"sha512-ZMkxaopfwKHwmEuGDYx7giNBdLxbHbRCWcQVA1D2eqE4crUguupfxej6s7UqbidYEwT69dkyumYkY8DPHIxF9g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@tinyhttp/content-disposition\": \"^2.2.0\",\n \"async-retry\": \"^1.3.3\",\n \"chalk\": \"^5.3.0\",\n \"ci-info\": \"^4.0.0\",\n \"cli-spinners\": \"^2.9.2\",\n \"commander\": \"^10.0.0\",\n \"eventemitter3\": \"^5.0.1\",\n \"filenamify\": \"^6.0.0\",\n \"fs-extra\": \"^11.1.1\",\n \"is-unicode-supported\": \"^2.0.0\",\n \"lifecycle-utils\": \"^2.0.1\",\n \"lodash.debounce\": \"^4.0.8\",\n \"lowdb\": \"^7.0.1\",\n \"pretty-bytes\": \"^6.1.0\",\n \"pretty-ms\": \"^8.0.0\",\n \"sleep-promise\": \"^9.1.0\",\n \"slice-ansi\": \"^7.1.0\",\n \"stdout-update\": \"^4.0.1\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"bin\": {\n \"ipull\": \"dist/cli/cli.js\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/ido-pluto/ipull?sponsor=1\"\n },\n \"optionalDependencies\": {\n \"@reflink/reflink\": \"^0.1.16\"\n }\n },\n \"node_modules/ipull/node_modules/commander\": {\n \"version\": \"10.0.1\",\n \"resolved\": \"https://registry.npmjs.org/commander/-/commander-10.0.1.tgz\",\n \"integrity\": \"sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=14\"\n }\n },\n \"node_modules/ipull/node_modules/lifecycle-utils\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/lifecycle-utils/-/lifecycle-utils-2.1.0.tgz\",\n \"integrity\": \"sha512-AnrXnE2/OF9PHCyFg0RSqsnQTzV991XaZA/buhFDoc58xU7rhSCDgCz/09Lqpsn4MpoPHt7TRAXV1kWZypFVsA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/ipull/node_modules/parse-ms\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/parse-ms/-/parse-ms-3.0.0.tgz\",\n \"integrity\": \"sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ipull/node_modules/pretty-ms\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/pretty-ms/-/pretty-ms-8.0.0.tgz\",\n \"integrity\": \"sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"parse-ms\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">=14.16\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/is-extendable\": {\n \"version\": \"0.1.1\",\n \"resolved\": \"https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz\",\n \"integrity\": \"sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/is-fullwidth-code-point\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz\",\n \"integrity\": \"sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/is-interactive\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz\",\n \"integrity\": \"sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/is-promise\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz\",\n \"integrity\": \"sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/is-stream\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz\",\n \"integrity\": \"sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/is-unicode-supported\": {\n \"version\": \"2.1.0\",\n \"resolved\": \"https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz\",\n \"integrity\": \"sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/isexe\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz\",\n \"integrity\": \"sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==\",\n \"license\": \"ISC\"\n },\n \"node_modules/jackspeak\": {\n \"version\": \"3.4.3\",\n \"resolved\": \"https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz\",\n \"integrity\": \"sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==\",\n \"license\": \"BlueOak-1.0.0\",\n \"dependencies\": {\n \"@isaacs/cliui\": \"^8.0.2\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n },\n \"optionalDependencies\": {\n \"@pkgjs/parseargs\": \"^0.11.0\"\n }\n },\n \"node_modules/jose\": {\n \"version\": \"6.1.3\",\n \"resolved\": \"https://registry.npmjs.org/jose/-/jose-6.1.3.tgz\",\n \"integrity\": \"sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"url\": \"https://github.com/sponsors/panva\"\n }\n },\n \"node_modules/joycon\": {\n \"version\": \"3.1.1\",\n \"resolved\": \"https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz\",\n \"integrity\": \"sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/js-tokens\": {\n \"version\": \"9.0.1\",\n \"resolved\": \"https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz\",\n \"integrity\": \"sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/js-yaml\": {\n \"version\": \"3.14.2\",\n \"resolved\": \"https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz\",\n \"integrity\": \"sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"argparse\": \"^1.0.7\",\n \"esprima\": \"^4.0.0\"\n },\n \"bin\": {\n \"js-yaml\": \"bin/js-yaml.js\"\n }\n },\n \"node_modules/json-schema-traverse\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz\",\n \"integrity\": \"sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/json-schema-typed\": {\n \"version\": \"8.0.2\",\n \"resolved\": \"https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz\",\n \"integrity\": \"sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==\",\n \"license\": \"BSD-2-Clause\",\n \"optional\": true\n },\n \"node_modules/jsonfile\": {\n \"version\": \"6.2.0\",\n \"resolved\": \"https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz\",\n \"integrity\": \"sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"universalify\": \"^2.0.0\"\n },\n \"optionalDependencies\": {\n \"graceful-fs\": \"^4.1.6\"\n }\n },\n \"node_modules/kareem\": {\n \"version\": \"2.6.3\",\n \"resolved\": \"https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz\",\n \"integrity\": \"sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==\",\n \"license\": \"Apache-2.0\",\n \"engines\": {\n \"node\": \">=12.0.0\"\n }\n },\n \"node_modules/kind-of\": {\n \"version\": \"6.0.3\",\n \"resolved\": \"https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz\",\n \"integrity\": \"sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/lifecycle-utils\": {\n \"version\": \"3.1.0\",\n \"resolved\": \"https://registry.npmjs.org/lifecycle-utils/-/lifecycle-utils-3.1.0.tgz\",\n \"integrity\": \"sha512-kVvegv+r/icjIo1dkHv1hznVQi4FzEVglJD2IU4w07HzevIyH3BAYsFZzEIbBk/nNZjXHGgclJ5g9rz9QdBCLw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/lilconfig\": {\n \"version\": \"3.1.3\",\n \"resolved\": \"https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz\",\n \"integrity\": \"sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=14\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/antonk52\"\n }\n },\n \"node_modules/lines-and-columns\": {\n \"version\": \"1.2.4\",\n \"resolved\": \"https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz\",\n \"integrity\": \"sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/load-tsconfig\": {\n \"version\": \"0.2.5\",\n \"resolved\": \"https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz\",\n \"integrity\": \"sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n }\n },\n \"node_modules/local-pkg\": {\n \"version\": \"0.5.1\",\n \"resolved\": \"https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz\",\n \"integrity\": \"sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"mlly\": \"^1.7.3\",\n \"pkg-types\": \"^1.2.1\"\n },\n \"engines\": {\n \"node\": \">=14\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/antfu\"\n }\n },\n \"node_modules/lodash.debounce\": {\n \"version\": \"4.0.8\",\n \"resolved\": \"https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz\",\n \"integrity\": \"sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/log-symbols\": {\n \"version\": \"7.0.1\",\n \"resolved\": \"https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz\",\n \"integrity\": \"sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"is-unicode-supported\": \"^2.0.0\",\n \"yoctocolors\": \"^2.1.1\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/loupe\": {\n \"version\": \"2.3.7\",\n \"resolved\": \"https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz\",\n \"integrity\": \"sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"get-func-name\": \"^2.0.1\"\n }\n },\n \"node_modules/lowdb\": {\n \"version\": \"7.0.1\",\n \"resolved\": \"https://registry.npmjs.org/lowdb/-/lowdb-7.0.1.tgz\",\n \"integrity\": \"sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"steno\": \"^4.0.2\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/typicode\"\n }\n },\n \"node_modules/lru-cache\": {\n \"version\": \"10.4.3\",\n \"resolved\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz\",\n \"integrity\": \"sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==\",\n \"license\": \"ISC\"\n },\n \"node_modules/magic-string\": {\n \"version\": \"0.30.21\",\n \"resolved\": \"https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz\",\n \"integrity\": \"sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jridgewell/sourcemap-codec\": \"^1.5.5\"\n }\n },\n \"node_modules/math-intrinsics\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz\",\n \"integrity\": \"sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n }\n },\n \"node_modules/media-typer\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz\",\n \"integrity\": \"sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/memjs\": {\n \"version\": \"1.3.2\",\n \"resolved\": \"https://registry.npmjs.org/memjs/-/memjs-1.3.2.tgz\",\n \"integrity\": \"sha512-qUEg2g8vxPe+zPn09KidjIStHPtoBO8Cttm8bgJFWWabbsjQ9Av9Ky+6UcvKx6ue0LLb/LEhtcyQpRyKfzeXcg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/memory-pager\": {\n \"version\": \"1.5.0\",\n \"resolved\": \"https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz\",\n \"integrity\": \"sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==\",\n \"license\": \"MIT\"\n },\n \"node_modules/memory-stream\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz\",\n \"integrity\": \"sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"readable-stream\": \"^3.4.0\"\n }\n },\n \"node_modules/merge-descriptors\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz\",\n \"integrity\": \"sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/merge-stream\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz\",\n \"integrity\": \"sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/mime-db\": {\n \"version\": \"1.54.0\",\n \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz\",\n \"integrity\": \"sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/mime-types\": {\n \"version\": \"3.0.2\",\n \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz\",\n \"integrity\": \"sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"mime-db\": \"^1.54.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/mimic-fn\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz\",\n \"integrity\": \"sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/mimic-function\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz\",\n \"integrity\": \"sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/minimatch\": {\n \"version\": \"9.0.5\",\n \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz\",\n \"integrity\": \"sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"brace-expansion\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">=16 || 14 >=14.17\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/minimist\": {\n \"version\": \"1.2.8\",\n \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz\",\n \"integrity\": \"sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/minipass\": {\n \"version\": \"7.1.2\",\n \"resolved\": \"https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz\",\n \"integrity\": \"sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==\",\n \"license\": \"ISC\",\n \"engines\": {\n \"node\": \">=16 || 14 >=14.17\"\n }\n },\n \"node_modules/minizlib\": {\n \"version\": \"2.1.2\",\n \"resolved\": \"https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz\",\n \"integrity\": \"sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"minipass\": \"^3.0.0\",\n \"yallist\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">= 8\"\n }\n },\n \"node_modules/minizlib/node_modules/minipass\": {\n \"version\": \"3.3.6\",\n \"resolved\": \"https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz\",\n \"integrity\": \"sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"yallist\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/mkdirp\": {\n \"version\": \"1.0.4\",\n \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz\",\n \"integrity\": \"sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"bin\": {\n \"mkdirp\": \"bin/cmd.js\"\n },\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/mlly\": {\n \"version\": \"1.8.0\",\n \"resolved\": \"https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz\",\n \"integrity\": \"sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"acorn\": \"^8.15.0\",\n \"pathe\": \"^2.0.3\",\n \"pkg-types\": \"^1.3.1\",\n \"ufo\": \"^1.6.1\"\n }\n },\n \"node_modules/mongodb\": {\n \"version\": \"6.20.0\",\n \"resolved\": \"https://registry.npmjs.org/mongodb/-/mongodb-6.20.0.tgz\",\n \"integrity\": \"sha512-Tl6MEIU3K4Rq3TSHd+sZQqRBoGlFsOgNrH5ltAcFBV62Re3Fd+FcaVf8uSEQFOJ51SDowDVttBTONMfoYWrWlQ==\",\n \"license\": \"Apache-2.0\",\n \"dependencies\": {\n \"@mongodb-js/saslprep\": \"^1.3.0\",\n \"bson\": \"^6.10.4\",\n \"mongodb-connection-string-url\": \"^3.0.2\"\n },\n \"engines\": {\n \"node\": \">=16.20.1\"\n },\n \"peerDependencies\": {\n \"@aws-sdk/credential-providers\": \"^3.188.0\",\n \"@mongodb-js/zstd\": \"^1.1.0 || ^2.0.0\",\n \"gcp-metadata\": \"^5.2.0\",\n \"kerberos\": \"^2.0.1\",\n \"mongodb-client-encryption\": \">=6.0.0 <7\",\n \"snappy\": \"^7.3.2\",\n \"socks\": \"^2.7.1\"\n },\n \"peerDependenciesMeta\": {\n \"@aws-sdk/credential-providers\": {\n \"optional\": true\n },\n \"@mongodb-js/zstd\": {\n \"optional\": true\n },\n \"gcp-metadata\": {\n \"optional\": true\n },\n \"kerberos\": {\n \"optional\": true\n },\n \"mongodb-client-encryption\": {\n \"optional\": true\n },\n \"snappy\": {\n \"optional\": true\n },\n \"socks\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/mongodb-connection-string-url\": {\n \"version\": \"3.0.2\",\n \"resolved\": \"https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz\",\n \"integrity\": \"sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==\",\n \"license\": \"Apache-2.0\",\n \"dependencies\": {\n \"@types/whatwg-url\": \"^11.0.2\",\n \"whatwg-url\": \"^14.1.0 || ^13.0.0\"\n }\n },\n \"node_modules/mongoose\": {\n \"version\": \"8.22.0\",\n \"resolved\": \"https://registry.npmjs.org/mongoose/-/mongoose-8.22.0.tgz\",\n \"integrity\": \"sha512-LKTPPqD3CVcSZJRzPcwKiSVYTmAvBZeVT0V34vUiqPEo9sBmOEg1y4TpDbUb90Zf2lO4N05ailQnKxiapCN08g==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"bson\": \"^6.10.4\",\n \"kareem\": \"2.6.3\",\n \"mongodb\": \"~6.20.0\",\n \"mpath\": \"0.9.0\",\n \"mquery\": \"5.0.0\",\n \"ms\": \"2.1.3\",\n \"sift\": \"17.1.3\"\n },\n \"engines\": {\n \"node\": \">=16.20.1\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/mongoose\"\n }\n },\n \"node_modules/mpath\": {\n \"version\": \"0.9.0\",\n \"resolved\": \"https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz\",\n \"integrity\": \"sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=4.0.0\"\n }\n },\n \"node_modules/mquery\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz\",\n \"integrity\": \"sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"debug\": \"4.x\"\n },\n \"engines\": {\n \"node\": \">=14.0.0\"\n }\n },\n \"node_modules/ms\": {\n \"version\": \"2.1.3\",\n \"resolved\": \"https://registry.npmjs.org/ms/-/ms-2.1.3.tgz\",\n \"integrity\": \"sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==\",\n \"license\": \"MIT\"\n },\n \"node_modules/mz\": {\n \"version\": \"2.7.0\",\n \"resolved\": \"https://registry.npmjs.org/mz/-/mz-2.7.0.tgz\",\n \"integrity\": \"sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"any-promise\": \"^1.0.0\",\n \"object-assign\": \"^4.0.1\",\n \"thenify-all\": \"^1.0.0\"\n }\n },\n \"node_modules/nanoid\": {\n \"version\": \"3.3.11\",\n \"resolved\": \"https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz\",\n \"integrity\": \"sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==\",\n \"dev\": true,\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"bin\": {\n \"nanoid\": \"bin/nanoid.cjs\"\n },\n \"engines\": {\n \"node\": \"^10 || ^12 || ^13.7 || ^14 || >=15.0.1\"\n }\n },\n \"node_modules/natural\": {\n \"version\": \"6.12.0\",\n \"resolved\": \"https://registry.npmjs.org/natural/-/natural-6.12.0.tgz\",\n \"integrity\": \"sha512-ZV/cuaxOvJ7CSxQRYHc6nlx7ql6hVPQc20N5ubdqVbotWnnqsNc+0/QG+ACIC3XPQ4rfrQrdC/1k47v1cSszTQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"afinn-165\": \"^1.0.2\",\n \"afinn-165-financialmarketnews\": \"^3.0.0\",\n \"apparatus\": \"^0.0.10\",\n \"dotenv\": \"^16.4.5\",\n \"memjs\": \"^1.3.2\",\n \"mongoose\": \"^8.2.0\",\n \"pg\": \"^8.11.3\",\n \"redis\": \"^4.6.13\",\n \"safe-stable-stringify\": \"^2.2.0\",\n \"stopwords-iso\": \"^1.1.0\",\n \"sylvester\": \"^0.0.12\",\n \"underscore\": \"^1.9.1\",\n \"uuid\": \"^9.0.1\",\n \"wordnet-db\": \"^3.1.11\"\n },\n \"engines\": {\n \"node\": \">=0.4.10\"\n }\n },\n \"node_modules/negotiator\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz\",\n \"integrity\": \"sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/node-addon-api\": {\n \"version\": \"8.5.0\",\n \"resolved\": \"https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz\",\n \"integrity\": \"sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"^18 || ^20 || >= 21\"\n }\n },\n \"node_modules/node-api-headers\": {\n \"version\": \"1.8.0\",\n \"resolved\": \"https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.8.0.tgz\",\n \"integrity\": \"sha512-jfnmiKWjRAGbdD1yQS28bknFM1tbHC1oucyuMPjmkEs+kpiu76aRs40WlTmBmyEgzDM76ge1DQ7XJ3R5deiVjQ==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/node-llama-cpp\": {\n \"version\": \"3.15.1\",\n \"resolved\": \"https://registry.npmjs.org/node-llama-cpp/-/node-llama-cpp-3.15.1.tgz\",\n \"integrity\": \"sha512-/fBNkuLGR2Q8xj2eeV12KXKZ9vCS2+o6aP11lW40pB9H6f0B3wOALi/liFrjhHukAoiH6C9wFTPzv6039+5DRA==\",\n \"hasInstallScript\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@huggingface/jinja\": \"^0.5.3\",\n \"async-retry\": \"^1.3.3\",\n \"bytes\": \"^3.1.2\",\n \"chalk\": \"^5.4.1\",\n \"chmodrp\": \"^1.0.2\",\n \"cmake-js\": \"^7.4.0\",\n \"cross-spawn\": \"^7.0.6\",\n \"env-var\": \"^7.5.0\",\n \"filenamify\": \"^6.0.0\",\n \"fs-extra\": \"^11.3.0\",\n \"ignore\": \"^7.0.4\",\n \"ipull\": \"^3.9.2\",\n \"is-unicode-supported\": \"^2.1.0\",\n \"lifecycle-utils\": \"^3.0.1\",\n \"log-symbols\": \"^7.0.0\",\n \"nanoid\": \"^5.1.5\",\n \"node-addon-api\": \"^8.3.1\",\n \"octokit\": \"^5.0.3\",\n \"ora\": \"^8.2.0\",\n \"pretty-ms\": \"^9.2.0\",\n \"proper-lockfile\": \"^4.1.2\",\n \"semver\": \"^7.7.1\",\n \"simple-git\": \"^3.27.0\",\n \"slice-ansi\": \"^7.1.0\",\n \"stdout-update\": \"^4.0.1\",\n \"strip-ansi\": \"^7.1.0\",\n \"validate-npm-package-name\": \"^6.0.0\",\n \"which\": \"^5.0.0\",\n \"yargs\": \"^17.7.2\"\n },\n \"bin\": {\n \"nlc\": \"dist/cli/cli.js\",\n \"node-llama-cpp\": \"dist/cli/cli.js\"\n },\n \"engines\": {\n \"node\": \">=20.0.0\"\n },\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/giladgd\"\n },\n \"optionalDependencies\": {\n \"@node-llama-cpp/linux-arm64\": \"3.15.1\",\n \"@node-llama-cpp/linux-armv7l\": \"3.15.1\",\n \"@node-llama-cpp/linux-x64\": \"3.15.1\",\n \"@node-llama-cpp/linux-x64-cuda\": \"3.15.1\",\n \"@node-llama-cpp/linux-x64-cuda-ext\": \"3.15.1\",\n \"@node-llama-cpp/linux-x64-vulkan\": \"3.15.1\",\n \"@node-llama-cpp/mac-arm64-metal\": \"3.15.1\",\n \"@node-llama-cpp/mac-x64\": \"3.15.1\",\n \"@node-llama-cpp/win-arm64\": \"3.15.1\",\n \"@node-llama-cpp/win-x64\": \"3.15.1\",\n \"@node-llama-cpp/win-x64-cuda\": \"3.15.1\",\n \"@node-llama-cpp/win-x64-cuda-ext\": \"3.15.1\",\n \"@node-llama-cpp/win-x64-vulkan\": \"3.15.1\"\n },\n \"peerDependencies\": {\n \"typescript\": \">=5.0.0\"\n },\n \"peerDependenciesMeta\": {\n \"typescript\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/node-llama-cpp/node_modules/isexe\": {\n \"version\": \"3.1.1\",\n \"resolved\": \"https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz\",\n \"integrity\": \"sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=16\"\n }\n },\n \"node_modules/node-llama-cpp/node_modules/nanoid\": {\n \"version\": \"5.1.6\",\n \"resolved\": \"https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz\",\n \"integrity\": \"sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true,\n \"bin\": {\n \"nanoid\": \"bin/nanoid.js\"\n },\n \"engines\": {\n \"node\": \"^18 || >=20\"\n }\n },\n \"node_modules/node-llama-cpp/node_modules/which\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/which/-/which-5.0.0.tgz\",\n \"integrity\": \"sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"isexe\": \"^3.1.1\"\n },\n \"bin\": {\n \"node-which\": \"bin/which.js\"\n },\n \"engines\": {\n \"node\": \"^18.17.0 || >=20.5.0\"\n }\n },\n \"node_modules/npm-run-path\": {\n \"version\": \"5.3.0\",\n \"resolved\": \"https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz\",\n \"integrity\": \"sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"path-key\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \"^12.20.0 || ^14.13.1 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/npm-run-path/node_modules/path-key\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz\",\n \"integrity\": \"sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/npmlog\": {\n \"version\": \"6.0.2\",\n \"resolved\": \"https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz\",\n \"integrity\": \"sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==\",\n \"deprecated\": \"This package is no longer supported.\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"are-we-there-yet\": \"^3.0.0\",\n \"console-control-strings\": \"^1.1.0\",\n \"gauge\": \"^4.0.3\",\n \"set-blocking\": \"^2.0.0\"\n },\n \"engines\": {\n \"node\": \"^12.13.0 || ^14.15.0 || >=16.0.0\"\n }\n },\n \"node_modules/object-assign\": {\n \"version\": \"4.1.1\",\n \"resolved\": \"https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz\",\n \"integrity\": \"sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==\",\n \"devOptional\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/object-inspect\": {\n \"version\": \"1.13.4\",\n \"resolved\": \"https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz\",\n \"integrity\": \"sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/octokit\": {\n \"version\": \"5.0.5\",\n \"resolved\": \"https://registry.npmjs.org/octokit/-/octokit-5.0.5.tgz\",\n \"integrity\": \"sha512-4+/OFSqOjoyULo7eN7EA97DE0Xydj/PW5aIckxqQIoFjFwqXKuFCvXUJObyJfBF9Khu4RL/jlDRI9FPaMGfPnw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@octokit/app\": \"^16.1.2\",\n \"@octokit/core\": \"^7.0.6\",\n \"@octokit/oauth-app\": \"^8.0.3\",\n \"@octokit/plugin-paginate-graphql\": \"^6.0.0\",\n \"@octokit/plugin-paginate-rest\": \"^14.0.0\",\n \"@octokit/plugin-rest-endpoint-methods\": \"^17.0.0\",\n \"@octokit/plugin-retry\": \"^8.0.3\",\n \"@octokit/plugin-throttling\": \"^11.0.3\",\n \"@octokit/request-error\": \"^7.0.2\",\n \"@octokit/types\": \"^16.0.0\",\n \"@octokit/webhooks\": \"^14.0.0\"\n },\n \"engines\": {\n \"node\": \">= 20\"\n }\n },\n \"node_modules/on-finished\": {\n \"version\": \"2.4.1\",\n \"resolved\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz\",\n \"integrity\": \"sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ee-first\": \"1.1.1\"\n },\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/once\": {\n \"version\": \"1.4.0\",\n \"resolved\": \"https://registry.npmjs.org/once/-/once-1.4.0.tgz\",\n \"integrity\": \"sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"wrappy\": \"1\"\n }\n },\n \"node_modules/onetime\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz\",\n \"integrity\": \"sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"mimic-fn\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ora\": {\n \"version\": \"8.2.0\",\n \"resolved\": \"https://registry.npmjs.org/ora/-/ora-8.2.0.tgz\",\n \"integrity\": \"sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"chalk\": \"^5.3.0\",\n \"cli-cursor\": \"^5.0.0\",\n \"cli-spinners\": \"^2.9.2\",\n \"is-interactive\": \"^2.0.0\",\n \"is-unicode-supported\": \"^2.0.0\",\n \"log-symbols\": \"^6.0.0\",\n \"stdin-discarder\": \"^0.2.2\",\n \"string-width\": \"^7.2.0\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ora/node_modules/emoji-regex\": {\n \"version\": \"10.6.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz\",\n \"integrity\": \"sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/ora/node_modules/log-symbols\": {\n \"version\": \"6.0.0\",\n \"resolved\": \"https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz\",\n \"integrity\": \"sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"chalk\": \"^5.3.0\",\n \"is-unicode-supported\": \"^1.3.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz\",\n \"integrity\": \"sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/ora/node_modules/string-width\": {\n \"version\": \"7.2.0\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz\",\n \"integrity\": \"sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^10.3.0\",\n \"get-east-asian-width\": \"^1.0.0\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/p-limit\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz\",\n \"integrity\": \"sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"yocto-queue\": \"^1.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/package-json-from-dist\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz\",\n \"integrity\": \"sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==\",\n \"license\": \"BlueOak-1.0.0\"\n },\n \"node_modules/parse-ms\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz\",\n \"integrity\": \"sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/parseurl\": {\n \"version\": \"1.3.3\",\n \"resolved\": \"https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz\",\n \"integrity\": \"sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/path-key\": {\n \"version\": \"3.1.1\",\n \"resolved\": \"https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz\",\n \"integrity\": \"sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/path-scurry\": {\n \"version\": \"1.11.1\",\n \"resolved\": \"https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz\",\n \"integrity\": \"sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==\",\n \"license\": \"BlueOak-1.0.0\",\n \"dependencies\": {\n \"lru-cache\": \"^10.2.0\",\n \"minipass\": \"^5.0.0 || ^6.0.2 || ^7.0.0\"\n },\n \"engines\": {\n \"node\": \">=16 || 14 >=14.18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/path-to-regexp\": {\n \"version\": \"8.3.0\",\n \"resolved\": \"https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz\",\n \"integrity\": \"sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/pathe\": {\n \"version\": \"2.0.3\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz\",\n \"integrity\": \"sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/pathval\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz\",\n \"integrity\": \"sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \"*\"\n }\n },\n \"node_modules/pg\": {\n \"version\": \"8.17.2\",\n \"resolved\": \"https://registry.npmjs.org/pg/-/pg-8.17.2.tgz\",\n \"integrity\": \"sha512-vjbKdiBJRqzcYw1fNU5KuHyYvdJ1qpcQg1CeBrHFqV1pWgHeVR6j/+kX0E1AAXfyuLUGY1ICrN2ELKA/z2HWzw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"pg-connection-string\": \"^2.10.1\",\n \"pg-pool\": \"^3.11.0\",\n \"pg-protocol\": \"^1.11.0\",\n \"pg-types\": \"2.2.0\",\n \"pgpass\": \"1.0.5\"\n },\n \"engines\": {\n \"node\": \">= 16.0.0\"\n },\n \"optionalDependencies\": {\n \"pg-cloudflare\": \"^1.3.0\"\n },\n \"peerDependencies\": {\n \"pg-native\": \">=3.0.1\"\n },\n \"peerDependenciesMeta\": {\n \"pg-native\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/pg-cloudflare\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz\",\n \"integrity\": \"sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/pg-connection-string\": {\n \"version\": \"2.10.1\",\n \"resolved\": \"https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.10.1.tgz\",\n \"integrity\": \"sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw==\",\n \"license\": \"MIT\"\n },\n \"node_modules/pg-int8\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz\",\n \"integrity\": \"sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==\",\n \"license\": \"ISC\",\n \"engines\": {\n \"node\": \">=4.0.0\"\n }\n },\n \"node_modules/pg-pool\": {\n \"version\": \"3.11.0\",\n \"resolved\": \"https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz\",\n \"integrity\": \"sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"pg\": \">=8.0\"\n }\n },\n \"node_modules/pg-protocol\": {\n \"version\": \"1.11.0\",\n \"resolved\": \"https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz\",\n \"integrity\": \"sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==\",\n \"license\": \"MIT\"\n },\n \"node_modules/pg-types\": {\n \"version\": \"2.2.0\",\n \"resolved\": \"https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz\",\n \"integrity\": \"sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"pg-int8\": \"1.0.1\",\n \"postgres-array\": \"~2.0.0\",\n \"postgres-bytea\": \"~1.0.0\",\n \"postgres-date\": \"~1.0.4\",\n \"postgres-interval\": \"^1.1.0\"\n },\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/pgpass\": {\n \"version\": \"1.0.5\",\n \"resolved\": \"https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz\",\n \"integrity\": \"sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"split2\": \"^4.1.0\"\n }\n },\n \"node_modules/picocolors\": {\n \"version\": \"1.1.1\",\n \"resolved\": \"https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz\",\n \"integrity\": \"sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==\",\n \"dev\": true,\n \"license\": \"ISC\"\n },\n \"node_modules/picomatch\": {\n \"version\": \"4.0.3\",\n \"resolved\": \"https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz\",\n \"integrity\": \"sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/jonschlinkert\"\n }\n },\n \"node_modules/pirates\": {\n \"version\": \"4.0.7\",\n \"resolved\": \"https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz\",\n \"integrity\": \"sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">= 6\"\n }\n },\n \"node_modules/pkce-challenge\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz\",\n \"integrity\": \"sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=16.20.0\"\n }\n },\n \"node_modules/pkg-types\": {\n \"version\": \"1.3.1\",\n \"resolved\": \"https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz\",\n \"integrity\": \"sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"confbox\": \"^0.1.8\",\n \"mlly\": \"^1.7.4\",\n \"pathe\": \"^2.0.1\"\n }\n },\n \"node_modules/postcss\": {\n \"version\": \"8.5.6\",\n \"resolved\": \"https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz\",\n \"integrity\": \"sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==\",\n \"dev\": true,\n \"funding\": [\n {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/postcss/\"\n },\n {\n \"type\": \"tidelift\",\n \"url\": \"https://tidelift.com/funding/github/npm/postcss\"\n },\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"dependencies\": {\n \"nanoid\": \"^3.3.11\",\n \"picocolors\": \"^1.1.1\",\n \"source-map-js\": \"^1.2.1\"\n },\n \"engines\": {\n \"node\": \"^10 || ^12 || >=14\"\n }\n },\n \"node_modules/postcss-load-config\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz\",\n \"integrity\": \"sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==\",\n \"dev\": true,\n \"funding\": [\n {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/postcss/\"\n },\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/ai\"\n }\n ],\n \"license\": \"MIT\",\n \"dependencies\": {\n \"lilconfig\": \"^3.1.1\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n },\n \"peerDependencies\": {\n \"jiti\": \">=1.21.0\",\n \"postcss\": \">=8.0.9\",\n \"tsx\": \"^4.8.1\",\n \"yaml\": \"^2.4.2\"\n },\n \"peerDependenciesMeta\": {\n \"jiti\": {\n \"optional\": true\n },\n \"postcss\": {\n \"optional\": true\n },\n \"tsx\": {\n \"optional\": true\n },\n \"yaml\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/postgres-array\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz\",\n \"integrity\": \"sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/postgres-bytea\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz\",\n \"integrity\": \"sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/postgres-date\": {\n \"version\": \"1.0.7\",\n \"resolved\": \"https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz\",\n \"integrity\": \"sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/postgres-interval\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz\",\n \"integrity\": \"sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"xtend\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/pretty-bytes\": {\n \"version\": \"6.1.1\",\n \"resolved\": \"https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz\",\n \"integrity\": \"sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"^14.13.1 || >=16.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/pretty-format\": {\n \"version\": \"29.7.0\",\n \"resolved\": \"https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz\",\n \"integrity\": \"sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jest/schemas\": \"^29.6.3\",\n \"ansi-styles\": \"^5.0.0\",\n \"react-is\": \"^18.0.0\"\n },\n \"engines\": {\n \"node\": \"^14.15.0 || ^16.10.0 || >=18.0.0\"\n }\n },\n \"node_modules/pretty-ms\": {\n \"version\": \"9.3.0\",\n \"resolved\": \"https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz\",\n \"integrity\": \"sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"parse-ms\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/proper-lockfile\": {\n \"version\": \"4.1.2\",\n \"resolved\": \"https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz\",\n \"integrity\": \"sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"graceful-fs\": \"^4.2.4\",\n \"retry\": \"^0.12.0\",\n \"signal-exit\": \"^3.0.2\"\n }\n },\n \"node_modules/proper-lockfile/node_modules/retry\": {\n \"version\": \"0.12.0\",\n \"resolved\": \"https://registry.npmjs.org/retry/-/retry-0.12.0.tgz\",\n \"integrity\": \"sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 4\"\n }\n },\n \"node_modules/proper-lockfile/node_modules/signal-exit\": {\n \"version\": \"3.0.7\",\n \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz\",\n \"integrity\": \"sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/proxy-addr\": {\n \"version\": \"2.0.7\",\n \"resolved\": \"https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz\",\n \"integrity\": \"sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"forwarded\": \"0.2.0\",\n \"ipaddr.js\": \"1.9.1\"\n },\n \"engines\": {\n \"node\": \">= 0.10\"\n }\n },\n \"node_modules/proxy-from-env\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz\",\n \"integrity\": \"sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/punycode\": {\n \"version\": \"2.3.1\",\n \"resolved\": \"https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz\",\n \"integrity\": \"sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=6\"\n }\n },\n \"node_modules/qmd\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"git+ssh://git@github.com/tobi/qmd.git#63028fd5e905f653bbb3f55e1857b48efba6ba6d\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.25.1\",\n \"node-llama-cpp\": \"^3.14.5\",\n \"sqlite-vec\": \"^0.1.7-alpha.2\",\n \"yaml\": \"^2.8.2\",\n \"zod\": \"^4.2.1\"\n },\n \"bin\": {\n \"qmd\": \"qmd\"\n },\n \"engines\": {\n \"bun\": \">=1.0.0\"\n },\n \"optionalDependencies\": {\n \"sqlite-vec-darwin-arm64\": \"^0.1.7-alpha.2\",\n \"sqlite-vec-darwin-x64\": \"^0.1.7-alpha.2\",\n \"sqlite-vec-linux-x64\": \"^0.1.7-alpha.2\",\n \"sqlite-vec-win32-x64\": \"^0.1.7-alpha.2\"\n },\n \"peerDependencies\": {\n \"typescript\": \"^5.9.3\"\n }\n },\n \"node_modules/qmd/node_modules/sqlite-vec-win32-x64\": {\n \"optional\": true\n },\n \"node_modules/qs\": {\n \"version\": \"6.14.1\",\n \"resolved\": \"https://registry.npmjs.org/qs/-/qs-6.14.1.tgz\",\n \"integrity\": \"sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==\",\n \"license\": \"BSD-3-Clause\",\n \"optional\": true,\n \"dependencies\": {\n \"side-channel\": \"^1.1.0\"\n },\n \"engines\": {\n \"node\": \">=0.6\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/range-parser\": {\n \"version\": \"1.2.1\",\n \"resolved\": \"https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz\",\n \"integrity\": \"sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/raw-body\": {\n \"version\": \"3.0.2\",\n \"resolved\": \"https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz\",\n \"integrity\": \"sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"bytes\": \"~3.1.2\",\n \"http-errors\": \"~2.0.1\",\n \"iconv-lite\": \"~0.7.0\",\n \"unpipe\": \"~1.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.10\"\n }\n },\n \"node_modules/rc\": {\n \"version\": \"1.2.8\",\n \"resolved\": \"https://registry.npmjs.org/rc/-/rc-1.2.8.tgz\",\n \"integrity\": \"sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==\",\n \"license\": \"(BSD-2-Clause OR MIT OR Apache-2.0)\",\n \"optional\": true,\n \"dependencies\": {\n \"deep-extend\": \"^0.6.0\",\n \"ini\": \"~1.3.0\",\n \"minimist\": \"^1.2.0\",\n \"strip-json-comments\": \"~2.0.1\"\n },\n \"bin\": {\n \"rc\": \"cli.js\"\n }\n },\n \"node_modules/react-is\": {\n \"version\": \"18.3.1\",\n \"resolved\": \"https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz\",\n \"integrity\": \"sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/readable-stream\": {\n \"version\": \"3.6.2\",\n \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz\",\n \"integrity\": \"sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"inherits\": \"^2.0.3\",\n \"string_decoder\": \"^1.1.1\",\n \"util-deprecate\": \"^1.0.1\"\n },\n \"engines\": {\n \"node\": \">= 6\"\n }\n },\n \"node_modules/readdirp\": {\n \"version\": \"4.1.2\",\n \"resolved\": \"https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz\",\n \"integrity\": \"sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">= 14.18.0\"\n },\n \"funding\": {\n \"type\": \"individual\",\n \"url\": \"https://paulmillr.com/funding/\"\n }\n },\n \"node_modules/redis\": {\n \"version\": \"4.7.1\",\n \"resolved\": \"https://registry.npmjs.org/redis/-/redis-4.7.1.tgz\",\n \"integrity\": \"sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==\",\n \"license\": \"MIT\",\n \"workspaces\": [\n \"./packages/*\"\n ],\n \"dependencies\": {\n \"@redis/bloom\": \"1.2.0\",\n \"@redis/client\": \"1.6.1\",\n \"@redis/graph\": \"1.1.1\",\n \"@redis/json\": \"1.0.7\",\n \"@redis/search\": \"1.2.0\",\n \"@redis/time-series\": \"1.1.0\"\n }\n },\n \"node_modules/require-directory\": {\n \"version\": \"2.1.1\",\n \"resolved\": \"https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz\",\n \"integrity\": \"sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/require-from-string\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz\",\n \"integrity\": \"sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/resolve-from\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz\",\n \"integrity\": \"sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/restore-cursor\": {\n \"version\": \"5.1.0\",\n \"resolved\": \"https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz\",\n \"integrity\": \"sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"onetime\": \"^7.0.0\",\n \"signal-exit\": \"^4.1.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/restore-cursor/node_modules/onetime\": {\n \"version\": \"7.0.0\",\n \"resolved\": \"https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz\",\n \"integrity\": \"sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"mimic-function\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/retry\": {\n \"version\": \"0.13.1\",\n \"resolved\": \"https://registry.npmjs.org/retry/-/retry-0.13.1.tgz\",\n \"integrity\": \"sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 4\"\n }\n },\n \"node_modules/rollup\": {\n \"version\": \"4.57.1\",\n \"resolved\": \"https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz\",\n \"integrity\": \"sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@types/estree\": \"1.0.8\"\n },\n \"bin\": {\n \"rollup\": \"dist/bin/rollup\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\",\n \"npm\": \">=8.0.0\"\n },\n \"optionalDependencies\": {\n \"@rollup/rollup-android-arm-eabi\": \"4.57.1\",\n \"@rollup/rollup-android-arm64\": \"4.57.1\",\n \"@rollup/rollup-darwin-arm64\": \"4.57.1\",\n \"@rollup/rollup-darwin-x64\": \"4.57.1\",\n \"@rollup/rollup-freebsd-arm64\": \"4.57.1\",\n \"@rollup/rollup-freebsd-x64\": \"4.57.1\",\n \"@rollup/rollup-linux-arm-gnueabihf\": \"4.57.1\",\n \"@rollup/rollup-linux-arm-musleabihf\": \"4.57.1\",\n \"@rollup/rollup-linux-arm64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-arm64-musl\": \"4.57.1\",\n \"@rollup/rollup-linux-loong64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-loong64-musl\": \"4.57.1\",\n \"@rollup/rollup-linux-ppc64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-ppc64-musl\": \"4.57.1\",\n \"@rollup/rollup-linux-riscv64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-riscv64-musl\": \"4.57.1\",\n \"@rollup/rollup-linux-s390x-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-x64-gnu\": \"4.57.1\",\n \"@rollup/rollup-linux-x64-musl\": \"4.57.1\",\n \"@rollup/rollup-openbsd-x64\": \"4.57.1\",\n \"@rollup/rollup-openharmony-arm64\": \"4.57.1\",\n \"@rollup/rollup-win32-arm64-msvc\": \"4.57.1\",\n \"@rollup/rollup-win32-ia32-msvc\": \"4.57.1\",\n \"@rollup/rollup-win32-x64-gnu\": \"4.57.1\",\n \"@rollup/rollup-win32-x64-msvc\": \"4.57.1\",\n \"fsevents\": \"~2.3.2\"\n }\n },\n \"node_modules/router\": {\n \"version\": \"2.2.0\",\n \"resolved\": \"https://registry.npmjs.org/router/-/router-2.2.0.tgz\",\n \"integrity\": \"sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"debug\": \"^4.4.0\",\n \"depd\": \"^2.0.0\",\n \"is-promise\": \"^4.0.0\",\n \"parseurl\": \"^1.3.3\",\n \"path-to-regexp\": \"^8.0.0\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n }\n },\n \"node_modules/safe-buffer\": {\n \"version\": \"5.2.1\",\n \"resolved\": \"https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz\",\n \"integrity\": \"sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==\",\n \"funding\": [\n {\n \"type\": \"github\",\n \"url\": \"https://github.com/sponsors/feross\"\n },\n {\n \"type\": \"patreon\",\n \"url\": \"https://www.patreon.com/feross\"\n },\n {\n \"type\": \"consulting\",\n \"url\": \"https://feross.org/support\"\n }\n ],\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/safe-stable-stringify\": {\n \"version\": \"2.5.0\",\n \"resolved\": \"https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz\",\n \"integrity\": \"sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/safer-buffer\": {\n \"version\": \"2.1.2\",\n \"resolved\": \"https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz\",\n \"integrity\": \"sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/section-matter\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz\",\n \"integrity\": \"sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"extend-shallow\": \"^2.0.1\",\n \"kind-of\": \"^6.0.0\"\n },\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/semver\": {\n \"version\": \"7.7.3\",\n \"resolved\": \"https://registry.npmjs.org/semver/-/semver-7.7.3.tgz\",\n \"integrity\": \"sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"bin\": {\n \"semver\": \"bin/semver.js\"\n },\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/send\": {\n \"version\": \"1.2.1\",\n \"resolved\": \"https://registry.npmjs.org/send/-/send-1.2.1.tgz\",\n \"integrity\": \"sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"debug\": \"^4.4.3\",\n \"encodeurl\": \"^2.0.0\",\n \"escape-html\": \"^1.0.3\",\n \"etag\": \"^1.8.1\",\n \"fresh\": \"^2.0.0\",\n \"http-errors\": \"^2.0.1\",\n \"mime-types\": \"^3.0.2\",\n \"ms\": \"^2.1.3\",\n \"on-finished\": \"^2.4.1\",\n \"range-parser\": \"^1.2.1\",\n \"statuses\": \"^2.0.2\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/serve-static\": {\n \"version\": \"2.2.1\",\n \"resolved\": \"https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz\",\n \"integrity\": \"sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"encodeurl\": \"^2.0.0\",\n \"escape-html\": \"^1.0.3\",\n \"parseurl\": \"^1.3.3\",\n \"send\": \"^1.2.0\"\n },\n \"engines\": {\n \"node\": \">= 18\"\n },\n \"funding\": {\n \"type\": \"opencollective\",\n \"url\": \"https://opencollective.com/express\"\n }\n },\n \"node_modules/set-blocking\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz\",\n \"integrity\": \"sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/setprototypeof\": {\n \"version\": \"1.2.0\",\n \"resolved\": \"https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz\",\n \"integrity\": \"sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/shebang-command\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz\",\n \"integrity\": \"sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"shebang-regex\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/shebang-regex\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz\",\n \"integrity\": \"sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/side-channel\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz\",\n \"integrity\": \"sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\",\n \"object-inspect\": \"^1.13.3\",\n \"side-channel-list\": \"^1.0.0\",\n \"side-channel-map\": \"^1.0.1\",\n \"side-channel-weakmap\": \"^1.0.2\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/side-channel-list\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz\",\n \"integrity\": \"sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"es-errors\": \"^1.3.0\",\n \"object-inspect\": \"^1.13.3\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/side-channel-map\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz\",\n \"integrity\": \"sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bound\": \"^1.0.2\",\n \"es-errors\": \"^1.3.0\",\n \"get-intrinsic\": \"^1.2.5\",\n \"object-inspect\": \"^1.13.3\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/side-channel-weakmap\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz\",\n \"integrity\": \"sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"call-bound\": \"^1.0.2\",\n \"es-errors\": \"^1.3.0\",\n \"get-intrinsic\": \"^1.2.5\",\n \"object-inspect\": \"^1.13.3\",\n \"side-channel-map\": \"^1.0.1\"\n },\n \"engines\": {\n \"node\": \">= 0.4\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/ljharb\"\n }\n },\n \"node_modules/sift\": {\n \"version\": \"17.1.3\",\n \"resolved\": \"https://registry.npmjs.org/sift/-/sift-17.1.3.tgz\",\n \"integrity\": \"sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==\",\n \"license\": \"MIT\"\n },\n \"node_modules/siginfo\": {\n \"version\": \"2.0.0\",\n \"resolved\": \"https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz\",\n \"integrity\": \"sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==\",\n \"dev\": true,\n \"license\": \"ISC\"\n },\n \"node_modules/signal-exit\": {\n \"version\": \"4.1.0\",\n \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz\",\n \"integrity\": \"sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==\",\n \"license\": \"ISC\",\n \"engines\": {\n \"node\": \">=14\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/isaacs\"\n }\n },\n \"node_modules/simple-git\": {\n \"version\": \"3.30.0\",\n \"resolved\": \"https://registry.npmjs.org/simple-git/-/simple-git-3.30.0.tgz\",\n \"integrity\": \"sha512-q6lxyDsCmEal/MEGhP1aVyQ3oxnagGlBDOVSIB4XUVLl1iZh0Pah6ebC9V4xBap/RfgP2WlI8EKs0WS0rMEJHg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"@kwsites/file-exists\": \"^1.1.1\",\n \"@kwsites/promise-deferred\": \"^1.1.1\",\n \"debug\": \"^4.4.0\"\n },\n \"funding\": {\n \"type\": \"github\",\n \"url\": \"https://github.com/steveukx/git-js?sponsor=1\"\n }\n },\n \"node_modules/sleep-promise\": {\n \"version\": \"9.1.0\",\n \"resolved\": \"https://registry.npmjs.org/sleep-promise/-/sleep-promise-9.1.0.tgz\",\n \"integrity\": \"sha512-UHYzVpz9Xn8b+jikYSD6bqvf754xL2uBUzDFwiU6NcdZeifPr6UfgU43xpkPu67VMS88+TI2PSI7Eohgqf2fKA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/slice-ansi\": {\n \"version\": \"7.1.2\",\n \"resolved\": \"https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz\",\n \"integrity\": \"sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-styles\": \"^6.2.1\",\n \"is-fullwidth-code-point\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/slice-ansi?sponsor=1\"\n }\n },\n \"node_modules/slice-ansi/node_modules/ansi-styles\": {\n \"version\": \"6.2.3\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz\",\n \"integrity\": \"sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/slice-ansi/node_modules/is-fullwidth-code-point\": {\n \"version\": \"5.1.0\",\n \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz\",\n \"integrity\": \"sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"get-east-asian-width\": \"^1.3.1\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/source-map\": {\n \"version\": \"0.7.6\",\n \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz\",\n \"integrity\": \"sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==\",\n \"dev\": true,\n \"license\": \"BSD-3-Clause\",\n \"engines\": {\n \"node\": \">= 12\"\n }\n },\n \"node_modules/source-map-js\": {\n \"version\": \"1.2.1\",\n \"resolved\": \"https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz\",\n \"integrity\": \"sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==\",\n \"dev\": true,\n \"license\": \"BSD-3-Clause\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/sparse-bitfield\": {\n \"version\": \"3.0.3\",\n \"resolved\": \"https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz\",\n \"integrity\": \"sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"memory-pager\": \"^1.0.2\"\n }\n },\n \"node_modules/split2\": {\n \"version\": \"4.2.0\",\n \"resolved\": \"https://registry.npmjs.org/split2/-/split2-4.2.0.tgz\",\n \"integrity\": \"sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==\",\n \"license\": \"ISC\",\n \"engines\": {\n \"node\": \">= 10.x\"\n }\n },\n \"node_modules/sprintf-js\": {\n \"version\": \"1.0.3\",\n \"resolved\": \"https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz\",\n \"integrity\": \"sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==\",\n \"license\": \"BSD-3-Clause\"\n },\n \"node_modules/sqlite-vec\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec/-/sqlite-vec-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-rNgRCv+4V4Ed3yc33Qr+nNmjhtrMnnHzXfLVPeGb28Dx5mmDL3Ngw/Wk8vhCGjj76+oC6gnkmMG8y73BZWGBwQ==\",\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"optionalDependencies\": {\n \"sqlite-vec-darwin-arm64\": \"0.1.7-alpha.2\",\n \"sqlite-vec-darwin-x64\": \"0.1.7-alpha.2\",\n \"sqlite-vec-linux-arm64\": \"0.1.7-alpha.2\",\n \"sqlite-vec-linux-x64\": \"0.1.7-alpha.2\",\n \"sqlite-vec-windows-x64\": \"0.1.7-alpha.2\"\n }\n },\n \"node_modules/sqlite-vec-darwin-arm64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-darwin-arm64/-/sqlite-vec-darwin-arm64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-raIATOqFYkeCHhb/t3r7W7Cf2lVYdf4J3ogJ6GFc8PQEgHCPEsi+bYnm2JT84MzLfTlSTIdxr4/NKv+zF7oLPw==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ]\n },\n \"node_modules/sqlite-vec-darwin-x64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-darwin-x64/-/sqlite-vec-darwin-x64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-jeZEELsQjjRsVojsvU5iKxOvkaVuE+JYC8Y4Ma8U45aAERrDYmqZoHvgSG7cg1PXL3bMlumFTAmHynf1y4pOzA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ]\n },\n \"node_modules/sqlite-vec-linux-arm64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-linux-arm64/-/sqlite-vec-linux-arm64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-6Spj4Nfi7tG13jsUG+W7jnT0bCTWbyPImu2M8nWp20fNrd1SZ4g3CSlDAK8GBdavX7wRlbBHCZ+BDa++rbDewA==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/sqlite-vec-linux-x64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-linux-x64/-/sqlite-vec-linux-x64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-IcgrbHaDccTVhXDf8Orwdc2+hgDLAFORl6OBUhcvlmwswwBP1hqBTSEhovClG4NItwTOBNgpwOoQ7Qp3VDPWLg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ]\n },\n \"node_modules/sqlite-vec-windows-x64\": {\n \"version\": \"0.1.7-alpha.2\",\n \"resolved\": \"https://registry.npmjs.org/sqlite-vec-windows-x64/-/sqlite-vec-windows-x64-0.1.7-alpha.2.tgz\",\n \"integrity\": \"sha512-TRP6hTjAcwvQ6xpCZvjP00pdlda8J38ArFy1lMYhtQWXiIBmWnhMaMbq4kaeCYwvTTddfidatRS+TJrwIKB/oQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"license\": \"MIT OR Apache\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ]\n },\n \"node_modules/stackback\": {\n \"version\": \"0.0.2\",\n \"resolved\": \"https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz\",\n \"integrity\": \"sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/statuses\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz\",\n \"integrity\": \"sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/std-env\": {\n \"version\": \"3.10.0\",\n \"resolved\": \"https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz\",\n \"integrity\": \"sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/stdin-discarder\": {\n \"version\": \"0.2.2\",\n \"resolved\": \"https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz\",\n \"integrity\": \"sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/stdout-update\": {\n \"version\": \"4.0.1\",\n \"resolved\": \"https://registry.npmjs.org/stdout-update/-/stdout-update-4.0.1.tgz\",\n \"integrity\": \"sha512-wiS21Jthlvl1to+oorePvcyrIkiG/6M3D3VTmDUlJm7Cy6SbFhKkAvX+YBuHLxck/tO3mrdpC/cNesigQc3+UQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-escapes\": \"^6.2.0\",\n \"ansi-styles\": \"^6.2.1\",\n \"string-width\": \"^7.1.0\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"engines\": {\n \"node\": \">=16.0.0\"\n }\n },\n \"node_modules/stdout-update/node_modules/ansi-styles\": {\n \"version\": \"6.2.3\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz\",\n \"integrity\": \"sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/stdout-update/node_modules/emoji-regex\": {\n \"version\": \"10.6.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz\",\n \"integrity\": \"sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/stdout-update/node_modules/string-width\": {\n \"version\": \"7.2.0\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz\",\n \"integrity\": \"sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^10.3.0\",\n \"get-east-asian-width\": \"^1.0.0\",\n \"strip-ansi\": \"^7.1.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/steno\": {\n \"version\": \"4.0.2\",\n \"resolved\": \"https://registry.npmjs.org/steno/-/steno-4.0.2.tgz\",\n \"integrity\": \"sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/typicode\"\n }\n },\n \"node_modules/stopwords-iso\": {\n \"version\": \"1.1.0\",\n \"resolved\": \"https://registry.npmjs.org/stopwords-iso/-/stopwords-iso-1.1.0.tgz\",\n \"integrity\": \"sha512-I6GPS/E0zyieHehMRPQcqkiBMJKGgLta+1hREixhoLPqEA0AlVFiC43dl8uPpmkkeRdDMzYRWFWk5/l9x7nmNg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/string_decoder\": {\n \"version\": \"1.3.0\",\n \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz\",\n \"integrity\": \"sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"safe-buffer\": \"~5.2.0\"\n }\n },\n \"node_modules/string-width\": {\n \"version\": \"5.1.2\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz\",\n \"integrity\": \"sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"eastasianwidth\": \"^0.2.0\",\n \"emoji-regex\": \"^9.2.2\",\n \"strip-ansi\": \"^7.0.1\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/string-width-cjs\": {\n \"name\": \"string-width\",\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/string-width-cjs/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/string-width-cjs/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\"\n },\n \"node_modules/string-width-cjs/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/strip-ansi\": {\n \"version\": \"7.1.2\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz\",\n \"integrity\": \"sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-regex\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/strip-ansi?sponsor=1\"\n }\n },\n \"node_modules/strip-ansi-cjs\": {\n \"name\": \"strip-ansi\",\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/strip-ansi-cjs/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/strip-bom-string\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz\",\n \"integrity\": \"sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/strip-final-newline\": {\n \"version\": \"3.0.0\",\n \"resolved\": \"https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz\",\n \"integrity\": \"sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/strip-json-comments\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz\",\n \"integrity\": \"sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.10.0\"\n }\n },\n \"node_modules/strip-literal\": {\n \"version\": \"2.1.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz\",\n \"integrity\": \"sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"js-tokens\": \"^9.0.1\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/antfu\"\n }\n },\n \"node_modules/sucrase\": {\n \"version\": \"3.35.1\",\n \"resolved\": \"https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz\",\n \"integrity\": \"sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@jridgewell/gen-mapping\": \"^0.3.2\",\n \"commander\": \"^4.0.0\",\n \"lines-and-columns\": \"^1.1.6\",\n \"mz\": \"^2.7.0\",\n \"pirates\": \"^4.0.1\",\n \"tinyglobby\": \"^0.2.11\",\n \"ts-interface-checker\": \"^0.1.9\"\n },\n \"bin\": {\n \"sucrase\": \"bin/sucrase\",\n \"sucrase-node\": \"bin/sucrase-node\"\n },\n \"engines\": {\n \"node\": \">=16 || 14 >=14.17\"\n }\n },\n \"node_modules/sucrase/node_modules/commander\": {\n \"version\": \"4.1.1\",\n \"resolved\": \"https://registry.npmjs.org/commander/-/commander-4.1.1.tgz\",\n \"integrity\": \"sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">= 6\"\n }\n },\n \"node_modules/sylvester\": {\n \"version\": \"0.0.12\",\n \"resolved\": \"https://registry.npmjs.org/sylvester/-/sylvester-0.0.12.tgz\",\n \"integrity\": \"sha512-SzRP5LQ6Ts2G5NyAa/jg16s8e3R7rfdFjizy1zeoecYWw+nGL+YA1xZvW/+iJmidBGSdLkuvdwTYEyJEb+EiUw==\",\n \"engines\": {\n \"node\": \">=0.2.6\"\n }\n },\n \"node_modules/tar\": {\n \"version\": \"6.2.1\",\n \"resolved\": \"https://registry.npmjs.org/tar/-/tar-6.2.1.tgz\",\n \"integrity\": \"sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==\",\n \"deprecated\": \"Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"chownr\": \"^2.0.0\",\n \"fs-minipass\": \"^2.0.0\",\n \"minipass\": \"^5.0.0\",\n \"minizlib\": \"^2.1.1\",\n \"mkdirp\": \"^1.0.3\",\n \"yallist\": \"^4.0.0\"\n },\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/tar/node_modules/minipass\": {\n \"version\": \"5.0.0\",\n \"resolved\": \"https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz\",\n \"integrity\": \"sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/thenify\": {\n \"version\": \"3.3.1\",\n \"resolved\": \"https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz\",\n \"integrity\": \"sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"any-promise\": \"^1.0.0\"\n }\n },\n \"node_modules/thenify-all\": {\n \"version\": \"1.6.0\",\n \"resolved\": \"https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz\",\n \"integrity\": \"sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"thenify\": \">= 3.1.0 < 4\"\n },\n \"engines\": {\n \"node\": \">=0.8\"\n }\n },\n \"node_modules/tinybench\": {\n \"version\": \"2.9.0\",\n \"resolved\": \"https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz\",\n \"integrity\": \"sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/tinyexec\": {\n \"version\": \"0.3.2\",\n \"resolved\": \"https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz\",\n \"integrity\": \"sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/tinyglobby\": {\n \"version\": \"0.2.15\",\n \"resolved\": \"https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz\",\n \"integrity\": \"sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"fdir\": \"^6.5.0\",\n \"picomatch\": \"^4.0.3\"\n },\n \"engines\": {\n \"node\": \">=12.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/SuperchupuDev\"\n }\n },\n \"node_modules/tinypool\": {\n \"version\": \"0.8.4\",\n \"resolved\": \"https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz\",\n \"integrity\": \"sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=14.0.0\"\n }\n },\n \"node_modules/tinyspy\": {\n \"version\": \"2.2.1\",\n \"resolved\": \"https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz\",\n \"integrity\": \"sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=14.0.0\"\n }\n },\n \"node_modules/toad-cache\": {\n \"version\": \"3.7.0\",\n \"resolved\": \"https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz\",\n \"integrity\": \"sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/toidentifier\": {\n \"version\": \"1.0.1\",\n \"resolved\": \"https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz\",\n \"integrity\": \"sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=0.6\"\n }\n },\n \"node_modules/tr46\": {\n \"version\": \"5.1.1\",\n \"resolved\": \"https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz\",\n \"integrity\": \"sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"punycode\": \"^2.3.1\"\n },\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/tree-kill\": {\n \"version\": \"1.2.2\",\n \"resolved\": \"https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz\",\n \"integrity\": \"sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"bin\": {\n \"tree-kill\": \"cli.js\"\n }\n },\n \"node_modules/ts-interface-checker\": {\n \"version\": \"0.1.13\",\n \"resolved\": \"https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz\",\n \"integrity\": \"sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==\",\n \"dev\": true,\n \"license\": \"Apache-2.0\"\n },\n \"node_modules/tsup\": {\n \"version\": \"8.5.1\",\n \"resolved\": \"https://registry.npmjs.org/tsup/-/tsup-8.5.1.tgz\",\n \"integrity\": \"sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"bundle-require\": \"^5.1.0\",\n \"cac\": \"^6.7.14\",\n \"chokidar\": \"^4.0.3\",\n \"consola\": \"^3.4.0\",\n \"debug\": \"^4.4.0\",\n \"esbuild\": \"^0.27.0\",\n \"fix-dts-default-cjs-exports\": \"^1.0.0\",\n \"joycon\": \"^3.1.1\",\n \"picocolors\": \"^1.1.1\",\n \"postcss-load-config\": \"^6.0.1\",\n \"resolve-from\": \"^5.0.0\",\n \"rollup\": \"^4.34.8\",\n \"source-map\": \"^0.7.6\",\n \"sucrase\": \"^3.35.0\",\n \"tinyexec\": \"^0.3.2\",\n \"tinyglobby\": \"^0.2.11\",\n \"tree-kill\": \"^1.2.2\"\n },\n \"bin\": {\n \"tsup\": \"dist/cli-default.js\",\n \"tsup-node\": \"dist/cli-node.js\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"peerDependencies\": {\n \"@microsoft/api-extractor\": \"^7.36.0\",\n \"@swc/core\": \"^1\",\n \"postcss\": \"^8.4.12\",\n \"typescript\": \">=4.5.0\"\n },\n \"peerDependenciesMeta\": {\n \"@microsoft/api-extractor\": {\n \"optional\": true\n },\n \"@swc/core\": {\n \"optional\": true\n },\n \"postcss\": {\n \"optional\": true\n },\n \"typescript\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/type-detect\": {\n \"version\": \"4.1.0\",\n \"resolved\": \"https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz\",\n \"integrity\": \"sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=4\"\n }\n },\n \"node_modules/type-is\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz\",\n \"integrity\": \"sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"content-type\": \"^1.0.5\",\n \"media-typer\": \"^1.1.0\",\n \"mime-types\": \"^3.0.0\"\n },\n \"engines\": {\n \"node\": \">= 0.6\"\n }\n },\n \"node_modules/typescript\": {\n \"version\": \"5.9.3\",\n \"resolved\": \"https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz\",\n \"integrity\": \"sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==\",\n \"devOptional\": true,\n \"license\": \"Apache-2.0\",\n \"bin\": {\n \"tsc\": \"bin/tsc\",\n \"tsserver\": \"bin/tsserver\"\n },\n \"engines\": {\n \"node\": \">=14.17\"\n }\n },\n \"node_modules/ufo\": {\n \"version\": \"1.6.3\",\n \"resolved\": \"https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz\",\n \"integrity\": \"sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/underscore\": {\n \"version\": \"1.13.7\",\n \"resolved\": \"https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz\",\n \"integrity\": \"sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==\",\n \"license\": \"MIT\"\n },\n \"node_modules/undici-types\": {\n \"version\": \"6.21.0\",\n \"resolved\": \"https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz\",\n \"integrity\": \"sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/universal-github-app-jwt\": {\n \"version\": \"2.2.2\",\n \"resolved\": \"https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-2.2.2.tgz\",\n \"integrity\": \"sha512-dcmbeSrOdTnsjGjUfAlqNDJrhxXizjAz94ija9Qw8YkZ1uu0d+GoZzyH+Jb9tIIqvGsadUfwg+22k5aDqqwzbw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/universal-user-agent\": {\n \"version\": \"7.0.3\",\n \"resolved\": \"https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz\",\n \"integrity\": \"sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/universalify\": {\n \"version\": \"2.0.1\",\n \"resolved\": \"https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz\",\n \"integrity\": \"sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 10.0.0\"\n }\n },\n \"node_modules/unpipe\": {\n \"version\": \"1.0.0\",\n \"resolved\": \"https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz\",\n \"integrity\": \"sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/url-join\": {\n \"version\": \"4.0.1\",\n \"resolved\": \"https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz\",\n \"integrity\": \"sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/util-deprecate\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz\",\n \"integrity\": \"sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/uuid\": {\n \"version\": \"9.0.1\",\n \"resolved\": \"https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz\",\n \"integrity\": \"sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==\",\n \"funding\": [\n \"https://github.com/sponsors/broofa\",\n \"https://github.com/sponsors/ctavan\"\n ],\n \"license\": \"MIT\",\n \"bin\": {\n \"uuid\": \"dist/bin/uuid\"\n }\n },\n \"node_modules/validate-npm-package-name\": {\n \"version\": \"6.0.2\",\n \"resolved\": \"https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.2.tgz\",\n \"integrity\": \"sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \"^18.17.0 || >=20.5.0\"\n }\n },\n \"node_modules/vary\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/vary/-/vary-1.1.2.tgz\",\n \"integrity\": \"sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">= 0.8\"\n }\n },\n \"node_modules/vite\": {\n \"version\": \"5.4.21\",\n \"resolved\": \"https://registry.npmjs.org/vite/-/vite-5.4.21.tgz\",\n \"integrity\": \"sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"esbuild\": \"^0.21.3\",\n \"postcss\": \"^8.4.43\",\n \"rollup\": \"^4.20.0\"\n },\n \"bin\": {\n \"vite\": \"bin/vite.js\"\n },\n \"engines\": {\n \"node\": \"^18.0.0 || >=20.0.0\"\n },\n \"funding\": {\n \"url\": \"https://github.com/vitejs/vite?sponsor=1\"\n },\n \"optionalDependencies\": {\n \"fsevents\": \"~2.3.3\"\n },\n \"peerDependencies\": {\n \"@types/node\": \"^18.0.0 || >=20.0.0\",\n \"less\": \"*\",\n \"lightningcss\": \"^1.21.0\",\n \"sass\": \"*\",\n \"sass-embedded\": \"*\",\n \"stylus\": \"*\",\n \"sugarss\": \"*\",\n \"terser\": \"^5.4.0\"\n },\n \"peerDependenciesMeta\": {\n \"@types/node\": {\n \"optional\": true\n },\n \"less\": {\n \"optional\": true\n },\n \"lightningcss\": {\n \"optional\": true\n },\n \"sass\": {\n \"optional\": true\n },\n \"sass-embedded\": {\n \"optional\": true\n },\n \"stylus\": {\n \"optional\": true\n },\n \"sugarss\": {\n \"optional\": true\n },\n \"terser\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/vite-node\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/vite-node/-/vite-node-1.6.1.tgz\",\n \"integrity\": \"sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"cac\": \"^6.7.14\",\n \"debug\": \"^4.3.4\",\n \"pathe\": \"^1.1.1\",\n \"picocolors\": \"^1.0.0\",\n \"vite\": \"^5.0.0\"\n },\n \"bin\": {\n \"vite-node\": \"vite-node.mjs\"\n },\n \"engines\": {\n \"node\": \"^18.0.0 || >=20.0.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n }\n },\n \"node_modules/vite-node/node_modules/pathe\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz\",\n \"integrity\": \"sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/vite/node_modules/@esbuild/aix-ppc64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz\",\n \"integrity\": \"sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"aix\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/android-arm\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz\",\n \"integrity\": \"sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/android-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/android-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"android\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/darwin-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/darwin-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"darwin\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/freebsd-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/freebsd-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"freebsd\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-arm\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz\",\n \"integrity\": \"sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==\",\n \"cpu\": [\n \"arm\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-ia32\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz\",\n \"integrity\": \"sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-loong64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz\",\n \"integrity\": \"sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==\",\n \"cpu\": [\n \"loong64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-mips64el\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz\",\n \"integrity\": \"sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==\",\n \"cpu\": [\n \"mips64el\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-ppc64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz\",\n \"integrity\": \"sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==\",\n \"cpu\": [\n \"ppc64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-riscv64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz\",\n \"integrity\": \"sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==\",\n \"cpu\": [\n \"riscv64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-s390x\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz\",\n \"integrity\": \"sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==\",\n \"cpu\": [\n \"s390x\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/linux-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"linux\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/netbsd-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"netbsd\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/openbsd-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"openbsd\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/sunos-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"sunos\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/win32-arm64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz\",\n \"integrity\": \"sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==\",\n \"cpu\": [\n \"arm64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/win32-ia32\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz\",\n \"integrity\": \"sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==\",\n \"cpu\": [\n \"ia32\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/@esbuild/win32-x64\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz\",\n \"integrity\": \"sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==\",\n \"cpu\": [\n \"x64\"\n ],\n \"dev\": true,\n \"license\": \"MIT\",\n \"optional\": true,\n \"os\": [\n \"win32\"\n ],\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/vite/node_modules/esbuild\": {\n \"version\": \"0.21.5\",\n \"resolved\": \"https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz\",\n \"integrity\": \"sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==\",\n \"dev\": true,\n \"hasInstallScript\": true,\n \"license\": \"MIT\",\n \"bin\": {\n \"esbuild\": \"bin/esbuild\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"optionalDependencies\": {\n \"@esbuild/aix-ppc64\": \"0.21.5\",\n \"@esbuild/android-arm\": \"0.21.5\",\n \"@esbuild/android-arm64\": \"0.21.5\",\n \"@esbuild/android-x64\": \"0.21.5\",\n \"@esbuild/darwin-arm64\": \"0.21.5\",\n \"@esbuild/darwin-x64\": \"0.21.5\",\n \"@esbuild/freebsd-arm64\": \"0.21.5\",\n \"@esbuild/freebsd-x64\": \"0.21.5\",\n \"@esbuild/linux-arm\": \"0.21.5\",\n \"@esbuild/linux-arm64\": \"0.21.5\",\n \"@esbuild/linux-ia32\": \"0.21.5\",\n \"@esbuild/linux-loong64\": \"0.21.5\",\n \"@esbuild/linux-mips64el\": \"0.21.5\",\n \"@esbuild/linux-ppc64\": \"0.21.5\",\n \"@esbuild/linux-riscv64\": \"0.21.5\",\n \"@esbuild/linux-s390x\": \"0.21.5\",\n \"@esbuild/linux-x64\": \"0.21.5\",\n \"@esbuild/netbsd-x64\": \"0.21.5\",\n \"@esbuild/openbsd-x64\": \"0.21.5\",\n \"@esbuild/sunos-x64\": \"0.21.5\",\n \"@esbuild/win32-arm64\": \"0.21.5\",\n \"@esbuild/win32-ia32\": \"0.21.5\",\n \"@esbuild/win32-x64\": \"0.21.5\"\n }\n },\n \"node_modules/vitest\": {\n \"version\": \"1.6.1\",\n \"resolved\": \"https://registry.npmjs.org/vitest/-/vitest-1.6.1.tgz\",\n \"integrity\": \"sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@vitest/expect\": \"1.6.1\",\n \"@vitest/runner\": \"1.6.1\",\n \"@vitest/snapshot\": \"1.6.1\",\n \"@vitest/spy\": \"1.6.1\",\n \"@vitest/utils\": \"1.6.1\",\n \"acorn-walk\": \"^8.3.2\",\n \"chai\": \"^4.3.10\",\n \"debug\": \"^4.3.4\",\n \"execa\": \"^8.0.1\",\n \"local-pkg\": \"^0.5.0\",\n \"magic-string\": \"^0.30.5\",\n \"pathe\": \"^1.1.1\",\n \"picocolors\": \"^1.0.0\",\n \"std-env\": \"^3.5.0\",\n \"strip-literal\": \"^2.0.0\",\n \"tinybench\": \"^2.5.1\",\n \"tinypool\": \"^0.8.3\",\n \"vite\": \"^5.0.0\",\n \"vite-node\": \"1.6.1\",\n \"why-is-node-running\": \"^2.2.2\"\n },\n \"bin\": {\n \"vitest\": \"vitest.mjs\"\n },\n \"engines\": {\n \"node\": \"^18.0.0 || >=20.0.0\"\n },\n \"funding\": {\n \"url\": \"https://opencollective.com/vitest\"\n },\n \"peerDependencies\": {\n \"@edge-runtime/vm\": \"*\",\n \"@types/node\": \"^18.0.0 || >=20.0.0\",\n \"@vitest/browser\": \"1.6.1\",\n \"@vitest/ui\": \"1.6.1\",\n \"happy-dom\": \"*\",\n \"jsdom\": \"*\"\n },\n \"peerDependenciesMeta\": {\n \"@edge-runtime/vm\": {\n \"optional\": true\n },\n \"@types/node\": {\n \"optional\": true\n },\n \"@vitest/browser\": {\n \"optional\": true\n },\n \"@vitest/ui\": {\n \"optional\": true\n },\n \"happy-dom\": {\n \"optional\": true\n },\n \"jsdom\": {\n \"optional\": true\n }\n }\n },\n \"node_modules/vitest/node_modules/pathe\": {\n \"version\": \"1.1.2\",\n \"resolved\": \"https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz\",\n \"integrity\": \"sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==\",\n \"dev\": true,\n \"license\": \"MIT\"\n },\n \"node_modules/webidl-conversions\": {\n \"version\": \"7.0.0\",\n \"resolved\": \"https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz\",\n \"integrity\": \"sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==\",\n \"license\": \"BSD-2-Clause\",\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/whatwg-url\": {\n \"version\": \"14.2.0\",\n \"resolved\": \"https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz\",\n \"integrity\": \"sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"tr46\": \"^5.1.0\",\n \"webidl-conversions\": \"^7.0.0\"\n },\n \"engines\": {\n \"node\": \">=18\"\n }\n },\n \"node_modules/which\": {\n \"version\": \"2.0.2\",\n \"resolved\": \"https://registry.npmjs.org/which/-/which-2.0.2.tgz\",\n \"integrity\": \"sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"isexe\": \"^2.0.0\"\n },\n \"bin\": {\n \"node-which\": \"bin/node-which\"\n },\n \"engines\": {\n \"node\": \">= 8\"\n }\n },\n \"node_modules/why-is-node-running\": {\n \"version\": \"2.3.0\",\n \"resolved\": \"https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz\",\n \"integrity\": \"sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"dependencies\": {\n \"siginfo\": \"^2.0.0\",\n \"stackback\": \"0.0.2\"\n },\n \"bin\": {\n \"why-is-node-running\": \"cli.js\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wide-align\": {\n \"version\": \"1.1.5\",\n \"resolved\": \"https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz\",\n \"integrity\": \"sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"dependencies\": {\n \"string-width\": \"^1.0.2 || 2 || 3 || 4\"\n }\n },\n \"node_modules/wide-align/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wide-align/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/wide-align/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wide-align/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wordnet-db\": {\n \"version\": \"3.1.14\",\n \"resolved\": \"https://registry.npmjs.org/wordnet-db/-/wordnet-db-3.1.14.tgz\",\n \"integrity\": \"sha512-zVyFsvE+mq9MCmwXUWHIcpfbrHHClZWZiVOzKSxNJruIcFn2RbY55zkhiAMMxM8zCVSmtNiViq8FsAZSFpMYag==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.6.0\"\n }\n },\n \"node_modules/wrap-ansi\": {\n \"version\": \"8.1.0\",\n \"resolved\": \"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz\",\n \"integrity\": \"sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-styles\": \"^6.1.0\",\n \"string-width\": \"^5.0.1\",\n \"strip-ansi\": \"^7.0.1\"\n },\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/wrap-ansi?sponsor=1\"\n }\n },\n \"node_modules/wrap-ansi-cjs\": {\n \"name\": \"wrap-ansi\",\n \"version\": \"7.0.0\",\n \"resolved\": \"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz\",\n \"integrity\": \"sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-styles\": \"^4.0.0\",\n \"string-width\": \"^4.1.0\",\n \"strip-ansi\": \"^6.0.0\"\n },\n \"engines\": {\n \"node\": \">=10\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/wrap-ansi?sponsor=1\"\n }\n },\n \"node_modules/wrap-ansi-cjs/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wrap-ansi-cjs/node_modules/ansi-styles\": {\n \"version\": \"4.3.0\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz\",\n \"integrity\": \"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"color-convert\": \"^2.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/wrap-ansi-cjs/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\"\n },\n \"node_modules/wrap-ansi-cjs/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wrap-ansi-cjs/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/wrap-ansi/node_modules/ansi-styles\": {\n \"version\": \"6.2.3\",\n \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz\",\n \"integrity\": \"sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12\"\n },\n \"funding\": {\n \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n }\n },\n \"node_modules/wrappy\": {\n \"version\": \"1.0.2\",\n \"resolved\": \"https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz\",\n \"integrity\": \"sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==\",\n \"license\": \"ISC\",\n \"optional\": true\n },\n \"node_modules/xtend\": {\n \"version\": \"4.0.2\",\n \"resolved\": \"https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz\",\n \"integrity\": \"sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=0.4\"\n }\n },\n \"node_modules/y18n\": {\n \"version\": \"5.0.8\",\n \"resolved\": \"https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz\",\n \"integrity\": \"sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=10\"\n }\n },\n \"node_modules/yallist\": {\n \"version\": \"4.0.0\",\n \"resolved\": \"https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz\",\n \"integrity\": \"sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==\",\n \"license\": \"ISC\"\n },\n \"node_modules/yaml\": {\n \"version\": \"2.8.2\",\n \"resolved\": \"https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz\",\n \"integrity\": \"sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"bin\": {\n \"yaml\": \"bin.mjs\"\n },\n \"engines\": {\n \"node\": \">= 14.6\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/eemeli\"\n }\n },\n \"node_modules/yargs\": {\n \"version\": \"17.7.2\",\n \"resolved\": \"https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz\",\n \"integrity\": \"sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"cliui\": \"^8.0.1\",\n \"escalade\": \"^3.1.1\",\n \"get-caller-file\": \"^2.0.5\",\n \"require-directory\": \"^2.1.1\",\n \"string-width\": \"^4.2.3\",\n \"y18n\": \"^5.0.5\",\n \"yargs-parser\": \"^21.1.1\"\n },\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/yargs-parser\": {\n \"version\": \"21.1.1\",\n \"resolved\": \"https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz\",\n \"integrity\": \"sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=12\"\n }\n },\n \"node_modules/yargs/node_modules/ansi-regex\": {\n \"version\": \"5.0.1\",\n \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/yargs/node_modules/emoji-regex\": {\n \"version\": \"8.0.0\",\n \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n \"license\": \"MIT\",\n \"optional\": true\n },\n \"node_modules/yargs/node_modules/string-width\": {\n \"version\": \"4.2.3\",\n \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz\",\n \"integrity\": \"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"emoji-regex\": \"^8.0.0\",\n \"is-fullwidth-code-point\": \"^3.0.0\",\n \"strip-ansi\": \"^6.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/yargs/node_modules/strip-ansi\": {\n \"version\": \"6.0.1\",\n \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz\",\n \"integrity\": \"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"dependencies\": {\n \"ansi-regex\": \"^5.0.1\"\n },\n \"engines\": {\n \"node\": \">=8\"\n }\n },\n \"node_modules/yocto-queue\": {\n \"version\": \"1.2.2\",\n \"resolved\": \"https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz\",\n \"integrity\": \"sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==\",\n \"dev\": true,\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=12.20\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/yoctocolors\": {\n \"version\": \"2.1.2\",\n \"resolved\": \"https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz\",\n \"integrity\": \"sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"engines\": {\n \"node\": \">=18\"\n },\n \"funding\": {\n \"url\": \"https://github.com/sponsors/sindresorhus\"\n }\n },\n \"node_modules/zod\": {\n \"version\": \"4.3.6\",\n \"resolved\": \"https://registry.npmjs.org/zod/-/zod-4.3.6.tgz\",\n \"integrity\": \"sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==\",\n \"license\": \"MIT\",\n \"optional\": true,\n \"funding\": {\n \"url\": \"https://github.com/sponsors/colinhacks\"\n }\n },\n \"node_modules/zod-to-json-schema\": {\n \"version\": \"3.25.1\",\n \"resolved\": \"https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz\",\n \"integrity\": \"sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==\",\n \"license\": \"ISC\",\n \"optional\": true,\n \"peerDependencies\": {\n \"zod\": \"^3.25 || ^4\"\n }\n }\n }\n}\n",197 "mimeType": null,198 "size": null,199 "icons": null,200 "annotations": null,201 "meta": null202 }203 ],204 "resource_templates": [],205 "tools": [206 {207 "name": "search.test.ts",208 "title": null,209 "description": "Script: search.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\n\nconst { execFileSyncMock, spawnSyncMock } = vi.hoisted(() => ({\n execFileSyncMock: vi.fn(),\n spawnSyncMock: vi.fn()\n}));\n\nvi.mock('child_process', () => ({\n execFileSync: execFileSyncMock,\n spawnSync: spawnSyncMock\n}));\n\nasync function loadSearchModule() {\n vi.resetModules();\n return await import('./search.js');\n}\n\nafterEach(() => {\n vi.clearAllMocks();\n});\n\ndescribe('search qmd dependency', () => {\n it('returns false when qmd is not available', async () => {\n spawnSyncMock.mockReturnValue({ error: new Error('missing') });\n const { hasQmd } = await loadSearchModule();\n expect(hasQmd()).toBe(false);\n });\n\n it('throws when searching without qmd installed', async () => {\n spawnSyncMock.mockReturnValue({ error: new Error('missing') });\n const { SearchEngine, QmdUnavailableError } = await loadSearchModule();\n const engine = new SearchEngine();\n expect(() => engine.search('hello')).toThrow(QmdUnavailableError);\n });\n\n it('converts qmd results and applies filters', async () => {\n spawnSyncMock.mockReturnValue({ error: undefined });\n execFileSyncMock.mockReturnValue(\n JSON.stringify([\n {\n docid: '1',\n score: 10,\n file: 'qmd://vault/projects/demo.md',\n title: 'Demo',\n snippet: '@@ -1,2 @@ (1 before, 2 after)\\nLine1\\nLine2\\nLine3\\nLine4'\n },\n {\n docid: '2',\n score: 5,\n file: 'qmd://vault/notes/other.md',\n title: 'Other',\n snippet: 'Other snippet'\n }\n ])\n );\n\n const { SearchEngine } = await loadSearchModule();\n const engine = new SearchEngine();\n engine.setCollection('vault');\n engine.setVaultPath('/vault');\n engine.setCollectionRoot('/vault');\n engine.addDocument({\n id: 'projects/demo',\n path: '/vault/projects/demo.md',\n category: 'projects',\n title: 'Demo',\n content: 'content',\n frontmatter: {},\n links: [],\n tags: ['keep'],\n modified: new Date()\n });\n\n const results = engine.search('hello', {\n tags: ['keep'],\n category: 'projects',\n limit: 5\n });\n\n expect(results).toHaveLength(1);\n expect(results[0].document.id).toBe('projects/demo');\n expect(results[0].document.path).toBe('/vault/projects/demo.md');\n expect(results[0].score).toBe(1);\n expect(results[0].snippet).not.toContain('@@');\n expect(results[0].snippet).toContain('Line1');\n });\n\n it('parses qmd output from error streams', async () => {\n spawnSyncMock.mockReturnValue({ error: undefined });\n execFileSyncMock.mockImplementation(() => {\n const err: any = new Error('qmd failed');\n err.stdout =\n 'noise\\n[{\"docid\":\"1\",\"score\":2,\"file\":\"qmd://vault/notes/a.md\",\"title\":\"A\",\"snippet\":\"hi\"}]';\n throw err;\n });\n\n const { SearchEngine } = await loadSearchModule();\n const engine = new SearchEngine();\n engine.setCollectionRoot('/vault');\n engine.setVaultPath('/vault');\n\n const results = engine.search('fallback', { limit: 1 });\n expect(results).toHaveLength(1);\n expect(results[0].document.path).toBe('/vault/notes/a.md');\n });\n});\n",210 "inputSchema": {},211 "outputSchema": null,212 "icons": null,213 "annotations": null,214 "meta": null,215 "execution": null216 },217 {218 "name": "search.ts",219 "title": null,220 "description": "Script: search.ts. Code:\n/**\n * ClawVault Search Engine - qmd Backend\n * Uses qmd CLI for BM25 and vector search\n */\n\nimport { execFileSync, spawnSync } from 'child_process';\nimport * as path from 'path';\nimport { Document, SearchResult, SearchOptions } from '../types.js';\n\nexport const QMD_INSTALL_URL = 'https://github.com/tobi/qmd';\nexport const QMD_INSTALL_COMMAND = 'bun install -g github:tobi/qmd';\nconst QMD_NOT_INSTALLED_MESSAGE = `ClawVault requires qmd. Install: ${QMD_INSTALL_COMMAND}`;\n\nexport class QmdUnavailableError extends Error {\n constructor(message: string = QMD_NOT_INSTALLED_MESSAGE) {\n super(message);\n this.name = 'QmdUnavailableError';\n }\n}\n\n/**\n * QMD search result format\n */\ninterface QmdResult {\n docid: string;\n score: number;\n file: string;\n title: string;\n snippet: string;\n}\n\nfunction ensureJsonArgs(args: string[]): string[] {\n return args.includes('--json') ? args : [...args, '--json'];\n}\n\nfunction tryParseJson(raw: string): unknown | null {\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\nfunction extractJsonPayload(raw: string): string | null {\n const start = raw.search(/[\\[{]/);\n if (start === -1) return null;\n const end = Math.max(raw.lastIndexOf(']'), raw.lastIndexOf('}'));\n if (end <= start) return null;\n return raw.slice(start, end + 1);\n}\n\nfunction parseQmdOutput(raw: string): QmdResult[] {\n const trimmed = raw.trim();\n if (!trimmed) return [];\n\n const direct = tryParseJson(trimmed);\n const extracted = direct ? null : extractJsonPayload(trimmed);\n const parsed = direct ?? (extracted ? tryParseJson(extracted) : null);\n\n if (!parsed) {\n throw new Error('qmd returned non-JSON output. Ensure qmd supports --json.');\n }\n\n if (Array.isArray(parsed)) {\n return parsed as QmdResult[];\n }\n\n if (parsed && typeof parsed === 'object') {\n const candidate = (parsed as { results?: unknown; items?: unknown; data?: unknown; }).results\n ?? (parsed as { results?: unknown; items?: unknown; data?: unknown; }).items\n ?? (parsed as { results?: unknown; items?: unknown; data?: unknown; }).data;\n\n if (Array.isArray(candidate)) {\n return candidate as QmdResult[];\n }\n }\n\n throw new Error('qmd returned an unexpected JSON shape.');\n}\n\nfunction ensureQmdAvailable(): void {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n}\n\n/**\n * Execute qmd command and return parsed JSON\n */\nfunction execQmd(args: string[]): QmdResult[] {\n ensureQmdAvailable();\n const finalArgs = ensureJsonArgs(args);\n\n try {\n const result = execFileSync('qmd', finalArgs, {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'pipe'],\n maxBuffer: 10 * 1024 * 1024 // 10MB\n });\n\n return parseQmdOutput(result);\n } catch (err: any) {\n if (err?.code === 'ENOENT') {\n throw new QmdUnavailableError();\n }\n\n const output = [err?.stdout, err?.stderr].filter(Boolean).join('\\n');\n if (output) {\n try {\n return parseQmdOutput(output);\n } catch {\n // Fall through to throw a helpful error\n }\n }\n\n const message = err?.message ? `qmd failed: ${err.message}` : 'qmd failed';\n throw new Error(message);\n }\n}\n\n/**\n * Check if qmd is available\n */\nexport function hasQmd(): boolean {\n const result = spawnSync('qmd', ['--version'], { stdio: 'ignore' });\n return !result.error;\n}\n\n/**\n * Trigger qmd update (reindex)\n */\nexport function qmdUpdate(collection?: string): void {\n ensureQmdAvailable();\n const args = ['update'];\n if (collection) {\n args.push('-c', collection);\n }\n execFileSync('qmd', args, { stdio: 'inherit' });\n}\n\n/**\n * Trigger qmd embed (create/update vector embeddings)\n */\nexport function qmdEmbed(collection?: string): void {\n ensureQmdAvailable();\n const args = ['embed'];\n if (collection) {\n args.push('-c', collection);\n }\n execFileSync('qmd', args, { stdio: 'inherit' });\n}\n\n/**\n * QMD Search Engine - wraps qmd CLI\n */\nexport class SearchEngine {\n private documents: Map<string, Document> = new Map();\n private collection: string = 'clawvault';\n private vaultPath: string = '';\n private collectionRoot: string = '';\n\n /**\n * Set the collection name (usually vault name)\n */\n setCollection(name: string): void {\n this.collection = name;\n }\n\n /**\n * Set the vault path for file resolution\n */\n setVaultPath(vaultPath: string): void {\n this.vaultPath = vaultPath;\n }\n\n /**\n * Set the collection root for qmd:// URI resolution\n */\n setCollectionRoot(root: string): void {\n this.collectionRoot = path.resolve(root);\n }\n\n /**\n * Add or update a document in the local cache\n * Note: qmd indexing happens via qmd update command\n */\n addDocument(doc: Document): void {\n this.documents.set(doc.id, doc);\n }\n\n /**\n * Remove a document from the local cache\n */\n removeDocument(id: string): void {\n this.documents.delete(id);\n }\n\n /**\n * No-op for qmd - indexing is managed externally\n */\n rebuildIDF(): void {\n // qmd handles this\n }\n\n /**\n * BM25 search via qmd\n */\n search(query: string, options: SearchOptions = {}): SearchResult[] {\n return this.runQmdQuery('search', query, options);\n }\n\n /**\n * Vector/semantic search via qmd vsearch\n */\n vsearch(query: string, options: SearchOptions = {}): SearchResult[] {\n return this.runQmdQuery('vsearch', query, options);\n }\n\n /**\n * Combined search with query expansion (qmd query command)\n */\n query(query: string, options: SearchOptions = {}): SearchResult[] {\n return this.runQmdQuery('query', query, options);\n }\n\n private runQmdQuery(command: 'search' | 'vsearch' | 'query', query: string, options: SearchOptions): SearchResult[] {\n const {\n limit = 10,\n minScore = 0,\n category,\n tags,\n fullContent = false\n } = options;\n\n if (!query.trim()) return [];\n\n const args = [\n command,\n query,\n '-n', String(limit * 2),\n '--json'\n ];\n\n if (this.collection) {\n args.push('-c', this.collection);\n }\n\n const qmdResults = execQmd(args);\n\n return this.convertResults(qmdResults, {\n limit,\n minScore,\n category,\n tags,\n fullContent\n });\n }\n\n /**\n * Convert qmd results to ClawVault SearchResult format\n */\n private convertResults(\n qmdResults: QmdResult[], \n options: SearchOptions\n ): SearchResult[] {\n const { limit = 10, minScore = 0, category, tags, fullContent = false } = options;\n \n const results: SearchResult[] = [];\n \n // Normalize scores - qmd uses different scales\n const maxScore = qmdResults[0]?.score || 1;\n \n for (const qr of qmdResults) {\n // Extract file path from qmd:// URI\n const filePath = this.qmdUriToPath(qr.file);\n const relativePath = this.vaultPath \n ? path.relative(this.vaultPath, filePath)\n : filePath;\n \n // Get document from cache or create minimal one\n const docId = relativePath.replace(/\\.md$/, '');\n let doc = this.documents.get(docId);\n \n // Determine category from path\n const parts = relativePath.split(path.sep);\n const docCategory = parts.length > 1 ? parts[0] : 'root';\n \n // Apply category filter\n if (category && docCategory !== category) continue;\n \n // Apply tag filter (only if we have the document cached)\n if (tags && tags.length > 0 && doc) {\n const docTags = new Set(doc.tags);\n if (!tags.some(t => docTags.has(t))) continue;\n }\n \n // Normalize score to 0-1 range\n const normalizedScore = maxScore > 0 ? qr.score / maxScore : 0;\n \n // Apply min score filter\n if (normalizedScore < minScore) continue;\n \n // Create document if not cached\n if (!doc) {\n doc = {\n id: docId,\n path: filePath,\n category: docCategory,\n title: qr.title || path.basename(relativePath, '.md'),\n content: '', // Content loaded separately if needed\n frontmatter: {},\n links: [],\n tags: [],\n modified: new Date()\n };\n }\n \n results.push({\n document: fullContent ? doc : { ...doc, content: '' },\n score: normalizedScore,\n snippet: this.cleanSnippet(qr.snippet),\n matchedTerms: [] // qmd doesn't provide this\n });\n \n if (results.length >= limit) break;\n }\n \n return results;\n }\n\n /**\n * Convert qmd:// URI to file path\n */\n private qmdUriToPath(uri: string): string {\n // qmd://collection/path/to/file.md -> actual path\n if (uri.startsWith('qmd://')) {\n const withoutScheme = uri.slice(6); // Remove 'qmd://'\n const slashIndex = withoutScheme.indexOf('/');\n if (slashIndex > -1) {\n // Get collection name and relative path\n const relativePath = withoutScheme.slice(slashIndex + 1);\n\n const root = this.collectionRoot || this.vaultPath;\n if (root) {\n return path.join(root, relativePath);\n }\n\n return relativePath;\n }\n }\n \n // Return as-is if not a qmd:// URI\n return uri;\n }\n\n /**\n * Clean up qmd snippet format\n */\n private cleanSnippet(snippet: string): string {\n if (!snippet) return '';\n \n // Remove diff-style markers like \"@@ -2,4 @@ (1 before, 67 after)\"\n return snippet\n .replace(/@@ [-+]?\\d+,?\\d* @@ \\([^)]+\\)/g, '')\n .trim()\n .split('\\n')\n .slice(0, 3)\n .join('\\n')\n .slice(0, 300);\n }\n\n /**\n * Get all cached documents\n */\n getAllDocuments(): Document[] {\n return [...this.documents.values()];\n }\n\n /**\n * Get document count\n */\n get size(): number {\n return this.documents.size;\n }\n\n /**\n * Clear the local document cache\n */\n clear(): void {\n this.documents.clear();\n }\n\n /**\n * Export documents for persistence\n */\n export(): { documents: Document[]; } {\n return {\n documents: [...this.documents.values()]\n };\n }\n\n /**\n * Import from persisted data\n */\n import(data: { documents: Document[]; }): void {\n this.clear();\n for (const doc of data.documents) {\n this.addDocument(doc);\n }\n }\n}\n\n/**\n * Find wiki-links in content\n */\nexport function extractWikiLinks(content: string): string[] {\n const matches = content.match(/\\[\\[([^\\]]+)\\]\\]/g) || [];\n return matches.map(m => m.slice(2, -2).toLowerCase());\n}\n\n/**\n * Find tags in content (#tag format)\n */\nexport function extractTags(content: string): string[] {\n const matches = content.match(/#[\\w-]+/g) || [];\n return [...new Set(matches.map(m => m.slice(1).toLowerCase()))];\n}\n",221 "inputSchema": {},222 "outputSchema": null,223 "icons": null,224 "annotations": null,225 "meta": null,226 "execution": null227 },228 {229 "name": "entity-index.ts",230 "title": null,231 "description": "Script: entity-index.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport matter from 'gray-matter';\n\nexport interface EntityEntry {\n path: string; // Relative path without .md (e.g., \"people/pedro\")\n aliases: string[]; // All names that link to this entity\n}\n\nexport interface EntityIndex {\n entries: Map<string, string>; // lowercase alias -> path\n byPath: Map<string, EntityEntry>;\n}\n\n/**\n * Build an entity index from all markdown files in the vault.\n * Extracts linkable names from:\n * - Filename (without .md)\n * - Frontmatter `title` field\n * - Frontmatter `aliases` array\n */\nexport function buildEntityIndex(vaultPath: string): EntityIndex {\n const entries = new Map<string, string>();\n const byPath = new Map<string, EntityEntry>();\n \n // Folders to scan for entities\n const entityFolders = ['people', 'projects', 'agents', 'lessons', 'decisions', 'commitments'];\n \n for (const folder of entityFolders) {\n const folderPath = path.join(vaultPath, folder);\n if (!fs.existsSync(folderPath)) continue;\n \n const files = fs.readdirSync(folderPath).filter(f => f.endsWith('.md'));\n \n for (const file of files) {\n const filePath = path.join(folderPath, file);\n const content = fs.readFileSync(filePath, 'utf-8');\n const { data: frontmatter } = matter(content);\n \n const relativePath = `${folder}/${file.replace('.md', '')}`;\n const baseName = file.replace('.md', '');\n \n const aliases: string[] = [baseName];\n \n // Add title if different from filename\n if (frontmatter.title && frontmatter.title.toLowerCase() !== baseName.toLowerCase()) {\n aliases.push(frontmatter.title);\n }\n \n // Add explicit aliases\n if (Array.isArray(frontmatter.aliases)) {\n aliases.push(...frontmatter.aliases);\n }\n \n // Register all aliases\n for (const alias of aliases) {\n const key = alias.toLowerCase();\n if (!entries.has(key)) {\n entries.set(key, relativePath);\n }\n }\n \n byPath.set(relativePath, { path: relativePath, aliases });\n }\n }\n \n return { entries, byPath };\n}\n\n/**\n * Get all entities sorted by alias length (longest first)\n * This ensures \"Justin Dukes\" is matched before \"Justin\"\n */\nexport function getSortedAliases(index: EntityIndex): Array<{ alias: string; path: string }> {\n const result: Array<{ alias: string; path: string }> = [];\n \n for (const [alias, path] of index.entries) {\n result.push({ alias, path });\n }\n \n // Sort by length descending\n result.sort((a, b) => b.alias.length - a.alias.length);\n \n return result;\n}\n",232 "inputSchema": {},233 "outputSchema": null,234 "icons": null,235 "annotations": null,236 "meta": null,237 "execution": null238 },239 {240 "name": "config.ts",241 "title": null,242 "description": "Script: config.ts. Code:\nimport * as path from 'path';\n\n/**\n * Get the vault path from CLAWVAULT_PATH env var or throw\n */\nexport function getVaultPath(): string {\n const vaultPath = process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n throw new Error('CLAWVAULT_PATH environment variable not set');\n }\n return path.resolve(vaultPath);\n}\n",243 "inputSchema": {},244 "outputSchema": null,245 "icons": null,246 "annotations": null,247 "meta": null,248 "execution": null249 },250 {251 "name": "vault.ts",252 "title": null,253 "description": "Script: vault.ts. Code:\n/**\n * ClawVault - The elephant's memory\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport matter from 'gray-matter';\nimport { glob } from 'glob';\nimport {\n VaultConfig,\n VaultMeta,\n Document,\n SearchResult,\n SearchOptions,\n StoreOptions,\n SyncOptions,\n SyncResult,\n DEFAULT_CATEGORIES,\n Category,\n MemoryType,\n TYPE_TO_CATEGORY,\n HandoffDocument,\n SessionRecap\n} from '../types.js';\nimport { SearchEngine, extractWikiLinks, extractTags, hasQmd, qmdUpdate, qmdEmbed, QmdUnavailableError } from './search.js';\n\nconst CONFIG_FILE = '.clawvault.json';\nconst INDEX_FILE = '.clawvault-index.json';\n\nexport class ClawVault {\n private config: VaultConfig;\n private search: SearchEngine;\n private initialized: boolean = false;\n\n constructor(vaultPath: string) {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n this.config = {\n path: path.resolve(vaultPath),\n name: path.basename(vaultPath),\n categories: DEFAULT_CATEGORIES,\n qmdCollection: undefined,\n qmdRoot: undefined\n };\n this.search = new SearchEngine();\n this.applyQmdConfig();\n }\n\n /**\n * Initialize a new vault\n */\n async init(options: Partial<VaultConfig> = {}): Promise<void> {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vaultPath = this.config.path;\n \n // Merge options\n this.config = { ...this.config, ...options };\n this.applyQmdConfig();\n \n // Create vault directory\n if (!fs.existsSync(vaultPath)) {\n fs.mkdirSync(vaultPath, { recursive: true });\n }\n\n // Create category directories\n for (const category of this.config.categories) {\n const catPath = path.join(vaultPath, category);\n if (!fs.existsSync(catPath)) {\n fs.mkdirSync(catPath, { recursive: true });\n }\n }\n\n // Create templates\n await this.createTemplates();\n\n // Create README\n const readmePath = path.join(vaultPath, 'README.md');\n if (!fs.existsSync(readmePath)) {\n fs.writeFileSync(readmePath, this.generateReadme());\n }\n\n // Save config\n const configPath = path.join(vaultPath, CONFIG_FILE);\n const meta: VaultMeta = {\n name: this.config.name,\n version: '1.0.0',\n created: new Date().toISOString(),\n lastUpdated: new Date().toISOString(),\n categories: this.config.categories,\n documentCount: 0,\n qmdCollection: this.getQmdCollection(),\n qmdRoot: this.getQmdRoot()\n };\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n\n this.initialized = true;\n }\n\n /**\n * Load an existing vault\n */\n async load(): Promise<void> {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vaultPath = this.config.path;\n const configPath = path.join(vaultPath, CONFIG_FILE);\n\n if (!fs.existsSync(configPath)) {\n throw new Error(`Not a ClawVault: ${vaultPath} (missing ${CONFIG_FILE})`);\n }\n\n const meta: VaultMeta = JSON.parse(fs.readFileSync(configPath, 'utf-8'));\n this.config.name = meta.name;\n this.config.categories = meta.categories;\n this.config.qmdCollection = meta.qmdCollection;\n this.config.qmdRoot = meta.qmdRoot;\n\n if (!meta.qmdCollection || !meta.qmdRoot) {\n meta.qmdCollection = meta.qmdCollection || meta.name;\n meta.qmdRoot = meta.qmdRoot || this.config.path;\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n }\n\n // Configure search engine with vault info\n this.applyQmdConfig(meta);\n\n // Index all documents (local cache)\n await this.reindex();\n this.initialized = true;\n }\n\n /**\n * Reindex all documents\n */\n async reindex(): Promise<number> {\n this.search.clear();\n \n const files = await glob('**/*.md', {\n cwd: this.config.path,\n ignore: ['**/node_modules/**', '**/.*']\n });\n\n for (const file of files) {\n const doc = await this.loadDocument(file);\n if (doc) {\n this.search.addDocument(doc);\n }\n }\n\n // Save index\n await this.saveIndex();\n\n return this.search.size;\n }\n\n /**\n * Load a document from disk\n */\n private async loadDocument(relativePath: string): Promise<Document | null> {\n try {\n const fullPath = path.join(this.config.path, relativePath);\n const content = fs.readFileSync(fullPath, 'utf-8');\n const { data: frontmatter, content: body } = matter(content);\n const stats = fs.statSync(fullPath);\n\n const parts = relativePath.split(path.sep);\n const category = parts.length > 1 ? parts[0] : 'root';\n const filename = path.basename(relativePath, '.md');\n\n return {\n id: relativePath.replace(/\\.md$/, ''),\n path: fullPath,\n category,\n title: (frontmatter.title as string) || filename,\n content: body,\n frontmatter,\n links: extractWikiLinks(body),\n tags: extractTags(body),\n modified: stats.mtime\n };\n } catch (err) {\n console.error(`Error loading ${relativePath}:`, err);\n return null;\n }\n }\n\n /**\n * Store a new document\n */\n async store(options: StoreOptions): Promise<Document> {\n const { \n category, \n title, \n content, \n frontmatter = {}, \n overwrite = false,\n qmdUpdate: triggerUpdate = false,\n qmdEmbed: triggerEmbed = false\n } = options;\n\n // Create filename from title\n const filename = this.slugify(title) + '.md';\n const relativePath = path.join(category, filename);\n const fullPath = path.join(this.config.path, relativePath);\n\n // Check if exists\n if (fs.existsSync(fullPath) && !overwrite) {\n throw new Error(`Document already exists: ${relativePath}. Use overwrite: true to replace.`);\n }\n\n // Ensure category directory exists\n const categoryPath = path.join(this.config.path, category);\n if (!fs.existsSync(categoryPath)) {\n fs.mkdirSync(categoryPath, { recursive: true });\n }\n\n // Build frontmatter with date\n const fm = {\n title,\n date: new Date().toISOString().split('T')[0],\n ...frontmatter\n };\n\n // Write file\n const fileContent = matter.stringify(content, fm);\n fs.writeFileSync(fullPath, fileContent);\n\n // Load and index the document\n const doc = await this.loadDocument(relativePath);\n if (doc) {\n this.search.addDocument(doc);\n await this.saveIndex();\n }\n\n // Trigger qmd reindex if requested\n if (triggerUpdate || triggerEmbed) {\n qmdUpdate(this.getQmdCollection());\n if (triggerEmbed) {\n qmdEmbed(this.getQmdCollection());\n }\n }\n\n return doc!;\n }\n\n /**\n * Quick store to inbox\n */\n async capture(note: string, title?: string): Promise<Document> {\n const autoTitle = title || `note-${Date.now()}`;\n return this.store({\n category: 'inbox',\n title: autoTitle,\n content: note\n });\n }\n\n /**\n * Search the vault (BM25 via qmd)\n */\n async find(query: string, options: SearchOptions = {}): Promise<SearchResult[]> {\n return this.search.search(query, options);\n }\n\n /**\n * Semantic/vector search (via qmd vsearch)\n */\n async vsearch(query: string, options: SearchOptions = {}): Promise<SearchResult[]> {\n return this.search.vsearch(query, options);\n }\n\n /**\n * Combined search with query expansion (via qmd query)\n */\n async query(query: string, options: SearchOptions = {}): Promise<SearchResult[]> {\n return this.search.query(query, options);\n }\n\n /**\n * Get a document by ID or path\n */\n async get(idOrPath: string): Promise<Document | null> {\n // Normalize path\n const normalized = idOrPath.replace(/\\.md$/, '');\n const docs = this.search.getAllDocuments();\n return docs.find(d => d.id === normalized) || null;\n }\n\n /**\n * List documents in a category\n */\n async list(category?: string): Promise<Document[]> {\n const docs = this.search.getAllDocuments();\n if (category) {\n return docs.filter(d => d.category === category);\n }\n return docs;\n }\n\n /**\n * Sync vault to another location (for Obsidian on Windows, etc.)\n */\n async sync(options: SyncOptions): Promise<SyncResult> {\n const { target, deleteOrphans = false, dryRun = false } = options;\n const result: SyncResult = {\n copied: [],\n deleted: [],\n unchanged: [],\n errors: []\n };\n\n // Get all source files\n const sourceFiles = await glob('**/*.md', {\n cwd: this.config.path,\n ignore: ['**/node_modules/**']\n });\n\n // Ensure target exists\n if (!dryRun && !fs.existsSync(target)) {\n fs.mkdirSync(target, { recursive: true });\n }\n\n // Copy files\n for (const file of sourceFiles) {\n const sourcePath = path.join(this.config.path, file);\n const targetPath = path.join(target, file);\n\n try {\n const sourceStats = fs.statSync(sourcePath);\n let shouldCopy = true;\n\n if (fs.existsSync(targetPath)) {\n const targetStats = fs.statSync(targetPath);\n if (sourceStats.mtime <= targetStats.mtime) {\n result.unchanged.push(file);\n shouldCopy = false;\n }\n }\n\n if (shouldCopy) {\n if (!dryRun) {\n const targetDir = path.dirname(targetPath);\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n fs.copyFileSync(sourcePath, targetPath);\n }\n result.copied.push(file);\n }\n } catch (err) {\n result.errors.push(`${file}: ${err}`);\n }\n }\n\n // Handle orphans in target\n if (deleteOrphans) {\n const targetFiles = await glob('**/*.md', { cwd: target });\n const sourceSet = new Set(sourceFiles);\n \n for (const file of targetFiles) {\n if (!sourceSet.has(file)) {\n if (!dryRun) {\n fs.unlinkSync(path.join(target, file));\n }\n result.deleted.push(file);\n }\n }\n }\n\n return result;\n }\n\n /**\n * Get vault statistics\n */\n async stats(): Promise<{\n documents: number;\n categories: { [key: string]: number };\n links: number;\n tags: string[];\n }> {\n const docs = this.search.getAllDocuments();\n const categories: { [key: string]: number } = {};\n const allTags = new Set<string>();\n let totalLinks = 0;\n\n for (const doc of docs) {\n categories[doc.category] = (categories[doc.category] || 0) + 1;\n totalLinks += doc.links.length;\n doc.tags.forEach(t => allTags.add(t));\n }\n\n return {\n documents: docs.length,\n categories,\n links: totalLinks,\n tags: [...allTags].sort()\n };\n }\n\n /**\n * Get all categories\n */\n getCategories(): Category[] {\n return this.config.categories;\n }\n\n /**\n * Check if vault is initialized\n */\n isInitialized(): boolean {\n return this.initialized;\n }\n\n /**\n * Get vault path\n */\n getPath(): string {\n return this.config.path;\n }\n\n /**\n * Get vault name\n */\n getName(): string {\n return this.config.name;\n }\n\n /**\n * Get qmd collection name\n */\n getQmdCollection(): string {\n return this.config.qmdCollection || this.config.name;\n }\n\n /**\n * Get qmd collection root\n */\n getQmdRoot(): string {\n return this.config.qmdRoot || this.config.path;\n }\n\n // === Memory Type System ===\n\n /**\n * Store a memory with type classification\n * Automatically routes to correct category based on type\n */\n async remember(\n type: MemoryType,\n title: string,\n content: string,\n frontmatter: Record<string, unknown> = {}\n ): Promise<Document> {\n const category = TYPE_TO_CATEGORY[type];\n return this.store({\n category,\n title,\n content,\n frontmatter: { ...frontmatter, memoryType: type }\n });\n }\n\n // === Handoff System ===\n\n /**\n * Create a session handoff document\n * Call this before context death or long pauses\n */\n async createHandoff(handoff: Omit<HandoffDocument, 'created'>): Promise<Document> {\n const now = new Date();\n const dateStr = now.toISOString().split('T')[0];\n const timeStr = now.toISOString().split('T')[1].slice(0, 5).replace(':', '');\n \n const fullHandoff: HandoffDocument = {\n ...handoff,\n created: now.toISOString()\n };\n\n const content = this.formatHandoff(fullHandoff);\n \n // Filter out undefined values to avoid yaml dump errors\n const frontmatter: Record<string, unknown> = {\n type: 'handoff',\n workingOn: handoff.workingOn,\n blocked: handoff.blocked,\n nextSteps: handoff.nextSteps\n };\n if (handoff.sessionKey) frontmatter.sessionKey = handoff.sessionKey;\n if (handoff.feeling) frontmatter.feeling = handoff.feeling;\n if (handoff.decisions) frontmatter.decisions = handoff.decisions;\n if (handoff.openQuestions) frontmatter.openQuestions = handoff.openQuestions;\n \n return this.store({\n category: 'handoffs',\n title: `handoff-${dateStr}-${timeStr}`,\n content,\n frontmatter\n });\n }\n\n /**\n * Format handoff as readable markdown\n */\n private formatHandoff(h: HandoffDocument): string {\n let md = `# Session Handoff\\n\\n`;\n md += `**Created:** ${h.created}\\n`;\n if (h.sessionKey) md += `**Session:** ${h.sessionKey}\\n`;\n if (h.feeling) md += `**Feeling:** ${h.feeling}\\n`;\n md += `\\n`;\n \n md += `## Working On\\n`;\n h.workingOn.forEach(w => md += `- ${w}\\n`);\n md += `\\n`;\n \n md += `## Blocked\\n`;\n if (h.blocked.length === 0) md += `- Nothing currently blocked\\n`;\n else h.blocked.forEach(b => md += `- ${b}\\n`);\n md += `\\n`;\n \n md += `## Next Steps\\n`;\n h.nextSteps.forEach(n => md += `- ${n}\\n`);\n \n if (h.decisions && h.decisions.length > 0) {\n md += `\\n## Decisions Made\\n`;\n h.decisions.forEach(d => md += `- ${d}\\n`);\n }\n \n if (h.openQuestions && h.openQuestions.length > 0) {\n md += `\\n## Open Questions\\n`;\n h.openQuestions.forEach(q => md += `- ${q}\\n`);\n }\n \n return md;\n }\n\n // === Session Recap (Bootstrap Hook) ===\n\n /**\n * Generate a session recap - who I was\n * Call this on bootstrap to restore context\n */\n async generateRecap(options: { handoffLimit?: number; brief?: boolean } = {}): Promise<SessionRecap> {\n const { handoffLimit = 3, brief = false } = options;\n \n // Get recent handoffs\n const handoffDocs = await this.list('handoffs');\n const recentHandoffs = handoffDocs\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())\n .slice(0, handoffLimit)\n .map(doc => this.parseHandoff(doc));\n \n // Get active projects\n const projectDocs = await this.list('projects');\n const activeProjects = projectDocs\n .filter(d => d.frontmatter.status !== 'completed' && d.frontmatter.status !== 'archived')\n .map(d => d.title);\n \n // Get pending commitments\n const commitmentDocs = await this.list('commitments');\n const pendingCommitments = commitmentDocs\n .filter(d => d.frontmatter.status !== 'done')\n .map(d => d.title);\n \n // Get recent decisions (new!)\n const decisionDocs = await this.list('decisions');\n const recentDecisions = decisionDocs\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())\n .slice(0, brief ? 3 : 5)\n .map(d => d.title);\n \n // Get recent lessons\n const lessonDocs = await this.list('lessons');\n const recentLessons = lessonDocs\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())\n .slice(0, brief ? 3 : 5)\n .map(d => d.title);\n \n // Get key relationships (skip in brief mode)\n let keyRelationships: string[] = [];\n if (!brief) {\n const peopleDocs = await this.list('people');\n keyRelationships = peopleDocs\n .filter(d => d.frontmatter.importance === 'high' || d.frontmatter.role)\n .map(d => `${d.title}${d.frontmatter.role ? ` (${d.frontmatter.role})` : ''}`);\n }\n \n // Derive emotional arc from recent handoffs\n const feelings = recentHandoffs\n .map(h => h.feeling)\n .filter(Boolean);\n const emotionalArc = feelings.length > 0 ? feelings.join(' \u2192 ') : undefined;\n \n return {\n generated: new Date().toISOString(),\n recentHandoffs,\n activeProjects,\n pendingCommitments,\n recentDecisions,\n recentLessons,\n keyRelationships,\n emotionalArc\n };\n }\n\n /**\n * Format recap as readable markdown for injection\n */\n formatRecap(recap: SessionRecap, options: { brief?: boolean } = {}): string {\n const { brief = false } = options;\n \n let md = `# Who I Was\\n\\n`;\n md += `*Generated: ${recap.generated}*\\n\\n`;\n \n if (recap.emotionalArc) {\n md += `**Emotional arc:** ${recap.emotionalArc}\\n\\n`;\n }\n \n if (recap.recentHandoffs.length > 0) {\n md += `## Recent Sessions\\n`;\n for (const h of recap.recentHandoffs) {\n if (brief) {\n // Compact format for brief mode\n md += `- **${h.created.split('T')[0]}:** ${h.workingOn.slice(0, 2).join(', ')}`;\n if (h.nextSteps.length > 0) md += ` \u2192 ${h.nextSteps[0]}`;\n md += `\\n`;\n } else {\n md += `\\n### ${h.created.split('T')[0]}\\n`;\n md += `**Working on:** ${h.workingOn.join(', ')}\\n`;\n if (h.blocked.length > 0) md += `**Blocked:** ${h.blocked.join(', ')}\\n`;\n md += `**Next:** ${h.nextSteps.join(', ')}\\n`;\n }\n }\n md += `\\n`;\n }\n \n if (recap.activeProjects.length > 0) {\n md += `## Active Projects\\n`;\n recap.activeProjects.forEach(p => md += `- ${p}\\n`);\n md += `\\n`;\n }\n \n if (recap.pendingCommitments.length > 0) {\n md += `## Pending Commitments\\n`;\n recap.pendingCommitments.forEach(c => md += `- ${c}\\n`);\n md += `\\n`;\n }\n \n if (recap.recentDecisions && recap.recentDecisions.length > 0) {\n md += `## Recent Decisions\\n`;\n recap.recentDecisions.forEach(d => md += `- ${d}\\n`);\n md += `\\n`;\n }\n \n if (recap.recentLessons.length > 0) {\n md += `## Recent Lessons\\n`;\n recap.recentLessons.forEach(l => md += `- ${l}\\n`);\n md += `\\n`;\n }\n \n if (!brief && recap.keyRelationships.length > 0) {\n md += `## Key People\\n`;\n recap.keyRelationships.forEach(r => md += `- ${r}\\n`);\n }\n \n return md;\n }\n\n /**\n * Parse a handoff document back into structured form\n */\n private parseHandoff(doc: Document): HandoffDocument {\n return {\n created: doc.frontmatter.date as string || doc.modified.toISOString(),\n sessionKey: doc.frontmatter.sessionKey as string,\n workingOn: (doc.frontmatter.workingOn as string[]) || [],\n blocked: (doc.frontmatter.blocked as string[]) || [],\n nextSteps: (doc.frontmatter.nextSteps as string[]) || [],\n decisions: doc.frontmatter.decisions as string[] | undefined,\n openQuestions: doc.frontmatter.openQuestions as string[] | undefined,\n feeling: doc.frontmatter.feeling as string\n };\n }\n\n // === Private helpers ===\n\n private applyQmdConfig(meta?: VaultMeta): void {\n const collection = meta?.qmdCollection || this.config.qmdCollection || this.config.name;\n const root = meta?.qmdRoot || this.config.qmdRoot || this.config.path;\n\n this.config.qmdCollection = collection;\n this.config.qmdRoot = root;\n\n this.search.setVaultPath(this.config.path);\n this.search.setCollection(collection);\n this.search.setCollectionRoot(root);\n }\n\n private slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .trim();\n }\n\n private async saveIndex(): Promise<void> {\n const indexPath = path.join(this.config.path, INDEX_FILE);\n const data = this.search.export();\n fs.writeFileSync(indexPath, JSON.stringify(data, null, 2));\n\n // Update config\n const configPath = path.join(this.config.path, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n const meta: VaultMeta = JSON.parse(fs.readFileSync(configPath, 'utf-8'));\n meta.lastUpdated = new Date().toISOString();\n meta.documentCount = this.search.size;\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n }\n }\n\n private async createTemplates(): Promise<void> {\n const templatesPath = path.join(this.config.path, 'templates');\n if (!fs.existsSync(templatesPath)) {\n fs.mkdirSync(templatesPath, { recursive: true });\n }\n\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(moduleDir, '../templates'),\n path.resolve(moduleDir, '../../templates')\n ];\n const builtinDir = candidates.find(dir => fs.existsSync(dir) && fs.statSync(dir).isDirectory());\n if (!builtinDir) return;\n\n for (const entry of fs.readdirSync(builtinDir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith('.md')) continue;\n if (entry.name === 'daily.md') continue;\n const sourcePath = path.join(builtinDir, entry.name);\n const targetPath = path.join(templatesPath, entry.name);\n if (!fs.existsSync(targetPath)) {\n fs.copyFileSync(sourcePath, targetPath);\n }\n }\n }\n\n private generateReadme(): string {\n return `# ${this.config.name} \ud83d\udc18\n\nAn elephant never forgets.\n\n## Structure\n\n${this.config.categories.map(c => `- \\`/${c}/\\` \u2014 ${this.getCategoryDescription(c)}`).join('\\n')}\n\n## Quick Search\n\n\\`\\`\\`bash\nclawvault search \"query\"\n\\`\\`\\`\n\n## Quick Capture\n\n\\`\\`\\`bash\nclawvault store --category inbox --title \"note\" --content \"...\"\n\\`\\`\\`\n\n---\n\n*Managed by [ClawVault](https://github.com/Versatly/clawvault)*\n`;\n }\n\n private getCategoryDescription(category: string): string {\n const descriptions: { [key: string]: string } = {\n // Memory type categories (Benthic's taxonomy)\n facts: 'Raw information, data points, things that are true',\n feelings: 'Emotional states, reactions, energy levels',\n decisions: 'Choices made with context and reasoning',\n lessons: 'What I learned, insights, patterns observed',\n commitments: 'Promises, goals, obligations to fulfill',\n preferences: 'Likes, dislikes, how I want things',\n people: 'Relationships, one file per person',\n projects: 'Active work, ventures, ongoing efforts',\n // System categories\n handoffs: 'Session bridges \u2014 what I was doing, what comes next',\n transcripts: 'Session summaries and logs',\n goals: 'Long-term and short-term objectives',\n patterns: 'Recurring behaviors (\u2192 lessons)',\n inbox: 'Quick capture \u2192 process later',\n templates: 'Templates for each document type'\n };\n return descriptions[category] || category;\n }\n}\n\n/**\n * Find and open the nearest vault (walks up directory tree)\n */\nexport async function findVault(startPath: string = process.cwd()): Promise<ClawVault | null> {\n let current = path.resolve(startPath);\n \n while (current !== path.dirname(current)) {\n const configPath = path.join(current, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n const vault = new ClawVault(current);\n await vault.load();\n return vault;\n }\n current = path.dirname(current);\n }\n \n return null;\n}\n\n/**\n * Create a new vault\n */\nexport async function createVault(vaultPath: string, options: Partial<VaultConfig> = {}): Promise<ClawVault> {\n const vault = new ClawVault(vaultPath);\n await vault.init(options);\n return vault;\n}\n",254 "inputSchema": {},255 "outputSchema": null,256 "icons": null,257 "annotations": null,258 "meta": null,259 "execution": null260 },261 {262 "name": "backlinks.ts",263 "title": null,264 "description": "Script: backlinks.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { buildEntityIndex, type EntityIndex } from './entity-index.js';\n\nconst CLAWVAULT_DIR = '.clawvault';\nconst BACKLINKS_FILE = 'backlinks.json';\nconst WIKI_LINK_REGEX = /\\[\\[([^\\]]+)\\]\\]/g;\n\nexport interface BacklinksScanResult {\n backlinks: Map<string, string[]>;\n orphans: Array<{ source: string; target: string }>;\n linkCount: number;\n}\n\nfunction ensureClawvaultDir(vaultPath: string): string {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\n\nfunction toVaultId(vaultPath: string, filePath: string): string {\n const relative = path.relative(vaultPath, filePath).replace(/\\.md$/, '');\n return relative.split(path.sep).join('/');\n}\n\nfunction normalizeLinkTarget(raw: string): string {\n let target = raw.trim();\n if (!target) return '';\n if (target.startsWith('[[') && target.endsWith(']]')) {\n target = target.slice(2, -2);\n }\n const pipeIndex = target.indexOf('|');\n if (pipeIndex !== -1) {\n target = target.slice(0, pipeIndex);\n }\n if (target.startsWith('#')) return '';\n const hashIndex = target.indexOf('#');\n if (hashIndex !== -1) {\n target = target.slice(0, hashIndex);\n }\n target = target.trim();\n if (!target) return '';\n if (target.endsWith('.md')) {\n target = target.slice(0, -3);\n }\n if (target.startsWith('/')) {\n target = target.slice(1);\n }\n return target.replace(/\\\\/g, '/');\n}\n\nfunction listMarkdownFiles(vaultPath: string): string[] {\n const files: string[] = [];\n const skipDirs = new Set(['archive', 'templates', 'node_modules']);\n\n function walk(dir: string): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name.startsWith('.') || skipDirs.has(entry.name)) continue;\n walk(fullPath);\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n files.push(fullPath);\n }\n }\n }\n\n walk(vaultPath);\n return files;\n}\n\nfunction buildKnownIds(vaultPath: string, files: string[]): {\n ids: Set<string>;\n idsLower: Map<string, string>;\n} {\n const ids = new Set<string>();\n const idsLower = new Map<string, string>();\n\n for (const file of files) {\n const id = toVaultId(vaultPath, file);\n ids.add(id);\n const lower = id.toLowerCase();\n if (!idsLower.has(lower)) {\n idsLower.set(lower, id);\n }\n }\n\n return { ids, idsLower };\n}\n\nfunction resolveTarget(\n target: string,\n known: { ids: Set<string>; idsLower: Map<string, string> },\n entityIndex?: EntityIndex\n): string | null {\n if (!target) return null;\n if (known.ids.has(target)) return target;\n const lower = target.toLowerCase();\n if (known.idsLower.has(lower)) return known.idsLower.get(lower)!;\n if (entityIndex?.entries.has(lower)) return entityIndex.entries.get(lower)!;\n return null;\n}\n\nexport function scanVaultLinks(\n vaultPath: string,\n options: { entityIndex?: EntityIndex } = {}\n): BacklinksScanResult {\n const files = listMarkdownFiles(vaultPath);\n const known = buildKnownIds(vaultPath, files);\n const entityIndex = options.entityIndex ?? buildEntityIndex(vaultPath);\n\n const backlinks = new Map<string, Set<string>>();\n const orphans: Array<{ source: string; target: string }> = [];\n let linkCount = 0;\n\n for (const file of files) {\n const sourceId = toVaultId(vaultPath, file);\n const content = fs.readFileSync(file, 'utf-8');\n const matches = content.match(WIKI_LINK_REGEX) || [];\n linkCount += matches.length;\n\n for (const match of matches) {\n const target = normalizeLinkTarget(match);\n if (!target) continue;\n const resolved = resolveTarget(target, known, entityIndex);\n if (!resolved) {\n orphans.push({ source: sourceId, target });\n continue;\n }\n if (!backlinks.has(resolved)) {\n backlinks.set(resolved, new Set());\n }\n backlinks.get(resolved)!.add(sourceId);\n }\n }\n\n const backlinksMap = new Map<string, string[]>();\n for (const [target, sources] of backlinks) {\n backlinksMap.set(target, [...sources].sort());\n }\n\n return { backlinks: backlinksMap, orphans, linkCount };\n}\n\nexport function writeBacklinksIndex(vaultPath: string, backlinks: Map<string, string[]>): void {\n const dir = ensureClawvaultDir(vaultPath);\n const output: Record<string, string[]> = {};\n\n const targets = [...backlinks.keys()].sort();\n for (const target of targets) {\n const sources = backlinks.get(target) || [];\n output[target] = [...new Set(sources)].sort();\n }\n\n fs.writeFileSync(path.join(dir, BACKLINKS_FILE), JSON.stringify(output, null, 2));\n}\n\nexport function readBacklinksIndex(vaultPath: string): Map<string, string[]> | null {\n const filePath = path.join(vaultPath, CLAWVAULT_DIR, BACKLINKS_FILE);\n if (!fs.existsSync(filePath)) return null;\n try {\n const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, string[]>;\n const map = new Map<string, string[]>();\n for (const [target, sources] of Object.entries(raw)) {\n if (Array.isArray(sources)) {\n map.set(target, sources);\n }\n }\n return map;\n } catch {\n return null;\n }\n}\n\nexport function rebuildBacklinksIndex(\n vaultPath: string,\n options: { entityIndex?: EntityIndex } = {}\n): BacklinksScanResult {\n const result = scanVaultLinks(vaultPath, options);\n writeBacklinksIndex(vaultPath, result.backlinks);\n return result;\n}\n",265 "inputSchema": {},266 "outputSchema": null,267 "icons": null,268 "annotations": null,269 "meta": null,270 "execution": null271 },272 {273 "name": "auto-linker.ts",274 "title": null,275 "description": "Script: auto-linker.ts. Code:\nimport { EntityIndex, getSortedAliases } from './entity-index.js';\n\ninterface ProtectedRange {\n start: number;\n end: number;\n}\n\n/**\n * Find all protected ranges in the content that should not be linked:\n * - Frontmatter (--- blocks)\n * - Code blocks (``` or ~~~)\n * - Inline code (`)\n * - Existing wiki links ([[...]])\n * - URLs\n */\nfunction findProtectedRanges(content: string): ProtectedRange[] {\n const ranges: ProtectedRange[] = [];\n \n // Frontmatter (must be at start)\n const fmMatch = content.match(/^---\\n[\\s\\S]*?\\n---/);\n if (fmMatch) {\n ranges.push({ start: 0, end: fmMatch[0].length });\n }\n \n // Code blocks\n const codeBlockRegex = /```[\\s\\S]*?```|~~~[\\s\\S]*?~~~/g;\n let match;\n while ((match = codeBlockRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n \n // Inline code\n const inlineCodeRegex = /`[^`]+`/g;\n while ((match = inlineCodeRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n \n // Existing wiki links\n const wikiLinkRegex = /\\[\\[[^\\]]+\\]\\]/g;\n while ((match = wikiLinkRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n \n // URLs\n const urlRegex = /https?:\\/\\/[^\\s)>\\]]+/g;\n while ((match = urlRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n \n return ranges;\n}\n\n/**\n * Check if a position is within any protected range\n */\nfunction isProtected(pos: number, ranges: ProtectedRange[]): boolean {\n return ranges.some(r => pos >= r.start && pos < r.end);\n}\n\nfunction createLineLookup(content: string): (pos: number) => number {\n const lines = content.split('\\n');\n let charPos = 0;\n const lineStarts: number[] = [];\n for (const line of lines) {\n lineStarts.push(charPos);\n charPos += line.length + 1;\n }\n\n return (pos: number) => {\n for (let i = lineStarts.length - 1; i >= 0; i--) {\n if (pos >= lineStarts[i]) return i + 1;\n }\n return 1;\n };\n}\n\n/**\n * Auto-link entities in markdown content.\n * Only links first occurrence of each entity.\n * Skips protected ranges (frontmatter, code, existing links, URLs).\n */\nexport function autoLink(content: string, index: EntityIndex): string {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const linkedEntities = new Set<string>();\n \n let result = content;\n let offset = 0; // Track position shifts from replacements\n \n for (const { alias, path } of sortedAliases) {\n // Skip if we already linked this entity\n if (linkedEntities.has(path)) continue;\n \n // Create word-boundary regex (case-insensitive)\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, 'gi');\n \n let match;\n while ((match = regex.exec(content)) !== null) {\n const originalPos = match.index;\n const adjustedPos = originalPos + offset;\n \n // Check if this position is protected in the ORIGINAL content\n if (isProtected(originalPos, protectedRanges)) continue;\n \n // Check if already inside a link in current result\n const beforeMatch = result.substring(0, adjustedPos);\n const openBrackets = (beforeMatch.match(/\\[\\[/g) || []).length;\n const closeBrackets = (beforeMatch.match(/\\]\\]/g) || []).length;\n if (openBrackets > closeBrackets) continue;\n \n // Found a valid match - replace it\n const originalText = match[0];\n const replacement = originalText.toLowerCase() === path.split('/').pop()?.toLowerCase()\n ? `[[${path}]]`\n : `[[${path}|${originalText}]]`;\n \n result = result.substring(0, adjustedPos) + replacement + result.substring(adjustedPos + originalText.length);\n offset += replacement.length - originalText.length;\n \n linkedEntities.add(path);\n break; // Only link first occurrence\n }\n }\n \n return result;\n}\n\n/**\n * Show what would be linked (dry run)\n */\nexport function dryRunLink(content: string, index: EntityIndex): Array<{ alias: string; path: string; line: number }> {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const linkedEntities = new Set<string>();\n const matches: Array<{ alias: string; path: string; line: number }> = [];\n const getLineNumber = createLineLookup(content);\n \n for (const { alias, path } of sortedAliases) {\n if (linkedEntities.has(path)) continue;\n \n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, 'gi');\n \n let match;\n while ((match = regex.exec(content)) !== null) {\n if (isProtected(match.index, protectedRanges)) continue;\n \n matches.push({\n alias: match[0],\n path,\n line: getLineNumber(match.index)\n });\n linkedEntities.add(path);\n break;\n }\n }\n \n return matches;\n}\n\n/**\n * Find unlinked mentions of entities (suggested links).\n */\nexport function findUnlinkedMentions(\n content: string,\n index: EntityIndex\n): Array<{ alias: string; path: string; line: number }> {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const matches: Array<{ alias: string; path: string; line: number }> = [];\n const seen = new Set<string>();\n const getLineNumber = createLineLookup(content);\n\n for (const { alias, path } of sortedAliases) {\n if (seen.has(path)) continue;\n\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, 'gi');\n\n let match;\n while ((match = regex.exec(content)) !== null) {\n if (isProtected(match.index, protectedRanges)) continue;\n\n matches.push({\n alias: match[0],\n path,\n line: getLineNumber(match.index)\n });\n seen.add(path);\n break;\n }\n }\n\n return matches;\n}\n",276 "inputSchema": {},277 "outputSchema": null,278 "icons": null,279 "annotations": null,280 "meta": null,281 "execution": null282 },283 {284 "name": "session-repair.ts",285 "title": null,286 "description": "Script: session-repair.ts. Code:\n/**\n * Session transcript repair logic\n * \n * Repairs corrupted OpenClaw session transcripts by:\n * 1. Finding aborted tool_use blocks (stopReason: \"aborted\", partialJson present)\n * 2. Finding orphaned tool_result messages that reference non-existent tool_use IDs\n * 3. Removing both the aborted entries and orphaned results\n * 4. Relinking parent chain references\n */\n\nimport * as fs from 'fs';\n\nexport interface TranscriptEntry {\n type: 'session' | 'message' | 'compaction' | 'custom' | 'thinking_level_change' | string;\n id: string;\n parentId: string | null;\n timestamp: string;\n message?: {\n role: 'user' | 'assistant' | 'toolResult' | 'system';\n content: Array<{\n type: string;\n id?: string;\n name?: string;\n arguments?: unknown;\n toolCallId?: string;\n toolUseId?: string;\n partialJson?: string;\n text?: string;\n }>;\n stopReason?: string;\n errorMessage?: string;\n };\n summary?: string;\n customType?: string;\n data?: unknown;\n thinkingLevel?: string;\n}\n\nexport interface ToolUseInfo {\n id: string;\n lineNumber: number;\n entryId: string;\n isAborted: boolean;\n isPartial: boolean;\n name?: string;\n}\n\nexport interface CorruptedEntry {\n lineNumber: number;\n entryId: string;\n type: 'aborted_tool_use' | 'orphaned_tool_result';\n toolUseId: string;\n description: string;\n}\n\nexport interface ParentRelink {\n lineNumber: number;\n entryId: string;\n oldParentId: string;\n newParentId: string;\n}\n\nexport interface RepairResult {\n sessionId: string;\n totalLines: number;\n corruptedEntries: CorruptedEntry[];\n parentRelinks: ParentRelink[];\n removedCount: number;\n relinkedCount: number;\n backupPath?: string;\n repaired: boolean;\n}\n\n/**\n * Parse a JSONL file into transcript entries with line numbers\n */\nexport function parseTranscript(filePath: string): Array<{ line: number; entry: TranscriptEntry; raw: string }> {\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n \n const entries: Array<{ line: number; entry: TranscriptEntry; raw: string }> = [];\n \n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i];\n try {\n const entry = JSON.parse(raw) as TranscriptEntry;\n entries.push({ line: i + 1, entry, raw });\n } catch {\n // Skip malformed lines\n console.warn(`Warning: Could not parse line ${i + 1}`);\n }\n }\n \n return entries;\n}\n\n/**\n * Extract all tool_use IDs from assistant messages\n */\nexport function extractToolUses(\n entries: Array<{ line: number; entry: TranscriptEntry }>\n): Map<string, ToolUseInfo> {\n const toolUses = new Map<string, ToolUseInfo>();\n \n for (const { line, entry } of entries) {\n if (entry.type !== 'message') continue;\n if (entry.message?.role !== 'assistant') continue;\n \n const isAborted = entry.message.stopReason === 'aborted';\n const content = entry.message.content || [];\n \n for (const block of content) {\n // Check for various tool call block types\n if (block.type === 'toolCall' || block.type === 'tool_use' || block.type === 'functionCall') {\n if (block.id) {\n const isPartial = !!block.partialJson;\n toolUses.set(block.id, {\n id: block.id,\n lineNumber: line,\n entryId: entry.id,\n isAborted: isAborted || isPartial,\n isPartial,\n name: block.name\n });\n }\n }\n }\n }\n \n return toolUses;\n}\n\n/**\n * Find orphaned tool_result messages that reference non-existent or aborted tool_use IDs\n */\nexport function findCorruptedEntries(\n entries: Array<{ line: number; entry: TranscriptEntry }>,\n toolUses: Map<string, ToolUseInfo>\n): {\n corrupted: CorruptedEntry[];\n entriesToRemove: Set<string>;\n} {\n const corrupted: CorruptedEntry[] = [];\n const entriesToRemove = new Set<string>();\n \n // First, mark aborted tool_uses for removal\n for (const [toolId, info] of toolUses) {\n if (info.isAborted) {\n corrupted.push({\n lineNumber: info.lineNumber,\n entryId: info.entryId,\n type: 'aborted_tool_use',\n toolUseId: toolId,\n description: `Aborted tool_use${info.name ? ` (${info.name})` : ''} with id: ${toolId}`\n });\n entriesToRemove.add(info.entryId);\n }\n }\n \n // Find orphaned tool_results\n for (const { line, entry } of entries) {\n if (entry.type !== 'message') continue;\n if (entry.message?.role !== 'toolResult') continue;\n \n // Get the tool_use ID this result references\n const content = entry.message.content || [];\n let toolCallId: string | undefined;\n \n // Check the message-level toolCallId (common pattern)\n const msg = entry.message as { toolCallId?: string; toolUseId?: string };\n toolCallId = msg.toolCallId || msg.toolUseId;\n \n // Also check content blocks for toolCallId\n if (!toolCallId) {\n for (const block of content) {\n if (block.toolCallId || block.toolUseId) {\n toolCallId = block.toolCallId || block.toolUseId;\n break;\n }\n }\n }\n \n if (!toolCallId) continue;\n \n // Check if the referenced tool_use exists and is valid\n const toolUse = toolUses.get(toolCallId);\n \n if (!toolUse || toolUse.isAborted) {\n corrupted.push({\n lineNumber: line,\n entryId: entry.id,\n type: 'orphaned_tool_result',\n toolUseId: toolCallId,\n description: toolUse\n ? `Orphaned tool_result references aborted tool_use: ${toolCallId}`\n : `Orphaned tool_result references non-existent tool_use: ${toolCallId}`\n });\n entriesToRemove.add(entry.id);\n }\n }\n \n return { corrupted, entriesToRemove };\n}\n\n/**\n * Compute parent chain relinks after removing entries\n */\nexport function computeParentRelinks(\n entries: Array<{ line: number; entry: TranscriptEntry }>,\n entriesToRemove: Set<string>\n): ParentRelink[] {\n const relinks: ParentRelink[] = [];\n \n // Build a map of entry ID to its parent ID\n const entryParents = new Map<string, string | null>();\n for (const { entry } of entries) {\n entryParents.set(entry.id, entry.parentId);\n }\n \n // For each entry that references a removed entry as parent, find the next valid ancestor\n for (const { line, entry } of entries) {\n if (entriesToRemove.has(entry.id)) continue; // Skip entries being removed\n if (!entry.parentId) continue;\n if (!entriesToRemove.has(entry.parentId)) continue; // Parent is valid\n \n // Find the next valid ancestor\n let newParentId: string | null = entry.parentId;\n while (newParentId && entriesToRemove.has(newParentId)) {\n newParentId = entryParents.get(newParentId) || null;\n }\n \n if (newParentId !== entry.parentId) {\n relinks.push({\n lineNumber: line,\n entryId: entry.id,\n oldParentId: entry.parentId,\n newParentId: newParentId || 'null'\n });\n }\n }\n \n return relinks;\n}\n\n/**\n * Analyze a session transcript for corruption without modifying it\n */\nexport function analyzeSession(filePath: string): RepairResult {\n const entries = parseTranscript(filePath);\n \n // Extract session ID from first entry\n const sessionEntry = entries.find(e => e.entry.type === 'session');\n const sessionId = sessionEntry?.entry.id || 'unknown';\n \n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const parentRelinks = computeParentRelinks(entries, entriesToRemove);\n \n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n repaired: false\n };\n}\n\n/**\n * Repair a session transcript\n */\nexport function repairSession(\n filePath: string,\n options: { backup?: boolean; dryRun?: boolean } = {}\n): RepairResult {\n const { backup = true, dryRun = false } = options;\n \n const entries = parseTranscript(filePath);\n \n // Extract session ID from first entry\n const sessionEntry = entries.find(e => e.entry.type === 'session');\n const sessionId = sessionEntry?.entry.id || 'unknown';\n \n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const parentRelinks = computeParentRelinks(entries, entriesToRemove);\n \n if (corrupted.length === 0) {\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: [],\n parentRelinks: [],\n removedCount: 0,\n relinkedCount: 0,\n repaired: false\n };\n }\n \n if (dryRun) {\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n repaired: false\n };\n }\n \n // Create backup if requested\n let backupPath: string | undefined;\n if (backup) {\n const timestamp = new Date().toISOString()\n .replace(/[:.]/g, '')\n .replace('T', '-')\n .slice(0, 15);\n backupPath = `${filePath}.backup-${timestamp}`;\n fs.copyFileSync(filePath, backupPath);\n }\n \n // Build relink map for quick lookup\n const relinkMap = new Map<string, string | null>();\n for (const relink of parentRelinks) {\n relinkMap.set(relink.entryId, relink.newParentId === 'null' ? null : relink.newParentId);\n }\n \n // Write repaired transcript\n const repairedLines: string[] = [];\n \n for (const { entry, raw } of entries) {\n // Skip removed entries\n if (entriesToRemove.has(entry.id)) continue;\n \n // Apply relinks if needed\n if (relinkMap.has(entry.id)) {\n const newEntry = { ...entry, parentId: relinkMap.get(entry.id) };\n repairedLines.push(JSON.stringify(newEntry));\n } else {\n repairedLines.push(raw);\n }\n }\n \n fs.writeFileSync(filePath, repairedLines.join('\\n') + '\\n');\n \n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n backupPath,\n repaired: true\n };\n}\n",287 "inputSchema": {},288 "outputSchema": null,289 "icons": null,290 "annotations": null,291 "meta": null,292 "execution": null293 },294 {295 "name": "template-engine.test.ts",296 "title": null,297 "description": "Script: template-engine.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport { buildTemplateVariables, renderTemplate } from './template-engine.js';\n\nafterEach(() => {\n vi.useRealTimers();\n});\n\ndescribe('template engine', () => {\n it('interpolates variables in frontmatter and body', () => {\n vi.useFakeTimers();\n vi.setSystemTime(new Date('2026-02-03T10:11:12Z'));\n\n const vars = buildTemplateVariables({ title: 'Alpha', type: 'decision' });\n const template = `---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\n---\n# {{title}}\n{{datetime}}\n`;\n\n const output = renderTemplate(template, vars);\n expect(output).toContain('title: \"Alpha\"');\n expect(output).toContain('date: 2026-02-03');\n expect(output).toContain('type: decision');\n expect(output).toContain('2026-02-03T10:11:12.000Z');\n });\n\n it('leaves unknown tokens untouched', () => {\n const vars = buildTemplateVariables({ title: 'Alpha', type: 'note' }, new Date('2026-02-03T00:00:00Z'));\n const output = renderTemplate('Hello {{unknown}}', vars);\n expect(output).toBe('Hello {{unknown}}');\n });\n});\n",298 "inputSchema": {},299 "outputSchema": null,300 "icons": null,301 "annotations": null,302 "meta": null,303 "execution": null304 },305 {306 "name": "session-utils.ts",307 "title": null,308 "description": "Script: session-utils.ts. Code:\n/**\n * Session discovery utilities for OpenClaw transcripts\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nexport interface SessionInfo {\n sessionId: string;\n sessionKey: string;\n agentId: string;\n filePath: string;\n updatedAt?: number;\n}\n\nexport interface SessionsStore {\n [sessionKey: string]: {\n sessionId: string;\n updatedAt?: number;\n [key: string]: unknown;\n };\n}\n\n/**\n * Get the OpenClaw agents directory\n */\nexport function getOpenClawAgentsDir(): string {\n return path.join(os.homedir(), '.openclaw', 'agents');\n}\n\n/**\n * Get the sessions directory for an agent\n */\nexport function getSessionsDir(agentId: string): string {\n return path.join(getOpenClawAgentsDir(), agentId, 'sessions');\n}\n\n/**\n * Get the path to sessions.json for an agent\n */\nexport function getSessionsJsonPath(agentId: string): string {\n return path.join(getSessionsDir(agentId), 'sessions.json');\n}\n\n/**\n * Get the path to a session JSONL file\n */\nexport function getSessionFilePath(agentId: string, sessionId: string): string {\n return path.join(getSessionsDir(agentId), `${sessionId}.jsonl`);\n}\n\n/**\n * List all available agents\n */\nexport function listAgents(): string[] {\n const agentsDir = getOpenClawAgentsDir();\n if (!fs.existsSync(agentsDir)) {\n return [];\n }\n \n return fs.readdirSync(agentsDir)\n .filter(name => {\n const sessionsDir = getSessionsDir(name);\n return fs.existsSync(sessionsDir) && fs.statSync(sessionsDir).isDirectory();\n });\n}\n\n/**\n * Load sessions.json for an agent\n */\nexport function loadSessionsStore(agentId: string): SessionsStore | null {\n const sessionsJsonPath = getSessionsJsonPath(agentId);\n if (!fs.existsSync(sessionsJsonPath)) {\n return null;\n }\n \n try {\n const content = fs.readFileSync(sessionsJsonPath, 'utf-8');\n return JSON.parse(content) as SessionsStore;\n } catch {\n return null;\n }\n}\n\n/**\n * Find the current/main session for an agent\n */\nexport function findMainSession(agentId: string): SessionInfo | null {\n const store = loadSessionsStore(agentId);\n if (!store) return null;\n \n // Look for the main session key pattern\n const mainKey = `agent:${agentId}:main`;\n const entry = store[mainKey];\n \n if (entry?.sessionId) {\n const filePath = getSessionFilePath(agentId, entry.sessionId);\n if (fs.existsSync(filePath)) {\n return {\n sessionId: entry.sessionId,\n sessionKey: mainKey,\n agentId,\n filePath,\n updatedAt: entry.updatedAt\n };\n }\n }\n \n return null;\n}\n\n/**\n * Find a session by ID\n */\nexport function findSessionById(agentId: string, sessionId: string): SessionInfo | null {\n const filePath = getSessionFilePath(agentId, sessionId);\n if (!fs.existsSync(filePath)) {\n return null;\n }\n \n const store = loadSessionsStore(agentId);\n let sessionKey: string | undefined;\n let updatedAt: number | undefined;\n \n if (store) {\n for (const [key, entry] of Object.entries(store)) {\n if (entry.sessionId === sessionId) {\n sessionKey = key;\n updatedAt = entry.updatedAt;\n break;\n }\n }\n }\n \n return {\n sessionId,\n sessionKey: sessionKey || `agent:${agentId}:unknown`,\n agentId,\n filePath,\n updatedAt\n };\n}\n\n/**\n * List all sessions for an agent\n */\nexport function listSessions(agentId: string): SessionInfo[] {\n const sessionsDir = getSessionsDir(agentId);\n if (!fs.existsSync(sessionsDir)) {\n return [];\n }\n \n const store = loadSessionsStore(agentId);\n const sessions: SessionInfo[] = [];\n \n const files = fs.readdirSync(sessionsDir)\n .filter(f => f.endsWith('.jsonl') && !f.includes('.backup') && !f.includes('.deleted') && !f.includes('.corrupted'));\n \n for (const file of files) {\n const sessionId = file.replace('.jsonl', '');\n const filePath = path.join(sessionsDir, file);\n \n let sessionKey = `agent:${agentId}:unknown`;\n let updatedAt: number | undefined;\n \n if (store) {\n for (const [key, entry] of Object.entries(store)) {\n if (entry.sessionId === sessionId) {\n sessionKey = key;\n updatedAt = entry.updatedAt;\n break;\n }\n }\n }\n \n sessions.push({\n sessionId,\n sessionKey,\n agentId,\n filePath,\n updatedAt\n });\n }\n \n return sessions.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n}\n\n/**\n * Create a backup of a session file\n */\nexport function backupSession(filePath: string): string {\n const timestamp = new Date().toISOString()\n .replace(/[:.]/g, '')\n .replace('T', '-')\n .slice(0, 15);\n \n const backupPath = `${filePath}.backup-${timestamp}`;\n fs.copyFileSync(filePath, backupPath);\n return backupPath;\n}\n",309 "inputSchema": {},310 "outputSchema": null,311 "icons": null,312 "annotations": null,313 "meta": null,314 "execution": null315 },316 {317 "name": "template-engine.ts",318 "title": null,319 "description": "Script: template-engine.ts. Code:\nexport interface TemplateVariables {\n title: string;\n date: string;\n datetime: string;\n type: string;\n}\n\nexport function buildTemplateVariables(\n input: Partial<TemplateVariables> = {},\n now: Date = new Date()\n): TemplateVariables {\n const datetime = input.datetime ?? now.toISOString();\n const date = input.date ?? datetime.split('T')[0];\n\n return {\n title: input.title ?? '',\n type: input.type ?? '',\n date,\n datetime\n };\n}\n\nexport function renderTemplate(template: string, variables: TemplateVariables): string {\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_-]+)\\s*\\}\\}/g, (match, key) => {\n const value = variables[key as keyof TemplateVariables];\n return value !== undefined ? String(value) : match;\n });\n}\n",320 "inputSchema": {},321 "outputSchema": null,322 "icons": null,323 "annotations": null,324 "meta": null,325 "execution": null326 },327 {328 "name": "time.ts",329 "title": null,330 "description": "Script: time.ts. Code:\nexport function formatAge(ms: number): string {\n if (!Number.isFinite(ms)) return 'unknown';\n const seconds = Math.max(0, Math.floor(ms / 1000));\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d ${hours % 24}h`;\n if (hours > 0) return `${hours}h ${minutes % 60}m`;\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\n}\n",331 "inputSchema": {},332 "outputSchema": null,333 "icons": null,334 "annotations": null,335 "meta": null,336 "execution": null337 },338 {339 "name": "backlinks.test.ts",340 "title": null,341 "description": "Script: backlinks.test.ts. Code:\nimport { afterEach, describe, expect, it } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { readBacklinksIndex, scanVaultLinks, writeBacklinksIndex } from './backlinks.js';\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-backlinks-'));\n}\n\nfunction writeFile(root: string, relative: string, content: string): void {\n const filePath = path.join(root, relative);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, content);\n}\n\ndescribe('backlinks scan', () => {\n it('builds backlinks and orphans', () => {\n const vaultPath = makeTempVaultDir();\n try {\n writeFile(vaultPath, 'people/alice.md', '# Alice');\n writeFile(vaultPath, 'projects/proj-x.md', '# Project X');\n writeFile(\n vaultPath,\n 'notes/a.md',\n 'Meeting with [[people/alice]] about [[projects/proj-x|Project X]].'\n );\n writeFile(vaultPath, 'notes/b.md', 'Follow up with [[people/alice]] and [[unknown]].');\n\n const result = scanVaultLinks(vaultPath);\n expect(result.linkCount).toBe(4);\n expect(result.backlinks.get('people/alice')).toEqual(['notes/a', 'notes/b']);\n expect(result.backlinks.get('projects/proj-x')).toEqual(['notes/a']);\n expect(result.orphans).toEqual([{ source: 'notes/b', target: 'unknown' }]);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('writes and reads backlinks index', () => {\n const vaultPath = makeTempVaultDir();\n try {\n writeFile(vaultPath, 'people/alice.md', '# Alice');\n writeFile(vaultPath, 'notes/a.md', 'See [[people/alice]].');\n\n const result = scanVaultLinks(vaultPath);\n writeBacklinksIndex(vaultPath, result.backlinks);\n\n const loaded = readBacklinksIndex(vaultPath);\n expect(loaded).not.toBeNull();\n expect(loaded?.get('people/alice')).toEqual(['notes/a']);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n});\n",342 "inputSchema": {},343 "outputSchema": null,344 "icons": null,345 "annotations": null,346 "meta": null,347 "execution": null348 },349 {350 "name": "template.test.ts",351 "title": null,352 "description": "Script: template.test.ts. Code:\nimport { afterEach, describe, expect, it } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { addTemplate, createFromTemplate, listTemplates } from './template.js';\n\nconst tempDirs: string[] = [];\n\nfunction makeTempDir(prefix: string): string {\n const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));\n tempDirs.push(dir);\n return dir;\n}\n\nafterEach(() => {\n while (tempDirs.length > 0) {\n const dir = tempDirs.pop();\n if (dir) {\n fs.rmSync(dir, { recursive: true, force: true });\n }\n }\n});\n\ndescribe('template command', () => {\n it('lists templates and creates a file from a custom template', () => {\n const vaultDir = makeTempDir('clawvault-template-vault-');\n const templatesDir = path.join(vaultDir, 'templates');\n fs.mkdirSync(templatesDir, { recursive: true });\n fs.writeFileSync(\n path.join(templatesDir, 'custom.md'),\n `---\ntitle: \"{{title}}\"\ndate: {{date}}\ntype: {{type}}\n---\n# {{title}}\n`\n );\n\n const builtinDir = makeTempDir('clawvault-template-builtin-');\n fs.writeFileSync(path.join(builtinDir, 'builtin.md'), '# Builtin');\n\n const names = listTemplates({ vaultPath: vaultDir, builtinDir });\n expect(names).toEqual(expect.arrayContaining(['custom', 'builtin']));\n\n const outputDir = makeTempDir('clawvault-template-out-');\n const result = createFromTemplate('custom', {\n vaultPath: vaultDir,\n builtinDir,\n cwd: outputDir,\n title: 'Alpha Plan',\n type: 'custom'\n });\n\n expect(result.outputPath).toBe(path.join(outputDir, 'alpha-plan.md'));\n const content = fs.readFileSync(result.outputPath, 'utf-8');\n expect(content).toContain('Alpha Plan');\n expect(content).not.toContain('{{title}}');\n });\n\n it('adds a template to the vault templates folder', () => {\n const vaultDir = makeTempDir('clawvault-template-vault-');\n const sourceDir = makeTempDir('clawvault-template-src-');\n const sourcePath = path.join(sourceDir, 'source.md');\n fs.writeFileSync(sourcePath, '# Custom Template');\n\n const result = addTemplate(sourcePath, { vaultPath: vaultDir, name: 'added' });\n const saved = fs.readFileSync(result.templatePath, 'utf-8');\n expect(saved).toBe('# Custom Template');\n });\n});\n",353 "inputSchema": {},354 "outputSchema": null,355 "icons": null,356 "annotations": null,357 "meta": null,358 "execution": null359 },360 {361 "name": "checkpoint.ts",362 "title": null,363 "description": "Script: checkpoint.ts. Code:\n/**\n * Quick checkpoint command - fast state save for context death resilience\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { execFileSync } from 'child_process';\n\nexport interface CheckpointOptions {\n workingOn?: string;\n focus?: string;\n blocked?: string;\n vaultPath: string;\n urgent?: boolean;\n}\n\nexport interface CheckpointData {\n timestamp: string;\n workingOn: string | null;\n focus: string | null;\n blocked: string | null;\n sessionId?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n sessionStartedAt?: string;\n urgent?: boolean;\n}\n\nexport interface SessionState {\n sessionId?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n startedAt?: string;\n}\n\nconst CLAWVAULT_DIR = '.clawvault';\nconst CHECKPOINT_FILE = 'last-checkpoint.json';\nconst SESSION_STATE_FILE = 'session-state.json';\nconst DIRTY_DEATH_FLAG = 'dirty-death.flag';\n\nlet pendingCheckpoint: NodeJS.Timeout | null = null;\nlet pendingData: { dir: string; data: CheckpointData } | null = null;\n\nfunction ensureClawvaultDir(vaultPath: string): string {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\n\nfunction writeCheckpointToDisk(dir: string, data: CheckpointData): void {\n const checkpointPath = path.join(dir, CHECKPOINT_FILE);\n fs.writeFileSync(checkpointPath, JSON.stringify(data, null, 2));\n\n const flagPath = path.join(dir, DIRTY_DEATH_FLAG);\n fs.writeFileSync(flagPath, data.timestamp);\n}\n\nfunction parseTokenEstimate(raw?: string): number | undefined {\n if (!raw) return undefined;\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction loadSessionState(dir: string): SessionState | null {\n const sessionStatePath = path.join(dir, SESSION_STATE_FILE);\n if (!fs.existsSync(sessionStatePath)) return null;\n try {\n return JSON.parse(fs.readFileSync(sessionStatePath, 'utf-8')) as SessionState;\n } catch {\n return null;\n }\n}\n\nfunction getEnvSessionState(): SessionState {\n return {\n sessionKey: process.env.OPENCLAW_SESSION_KEY,\n model: process.env.OPENCLAW_MODEL,\n tokenEstimate: parseTokenEstimate(\n process.env.OPENCLAW_TOKEN_ESTIMATE || process.env.OPENCLAW_CONTEXT_TOKENS\n )\n };\n}\n\nfunction triggerUrgentWake(data: CheckpointData): void {\n const summary = [\n data.workingOn ? `Working on: ${data.workingOn}` : null,\n data.focus ? `Focus: ${data.focus}` : null,\n data.blocked ? `Blocked: ${data.blocked}` : null\n ].filter(Boolean).join(' | ');\n\n const text = summary\n ? `Urgent checkpoint saved. ${summary}`\n : 'Urgent checkpoint saved.';\n\n try {\n execFileSync('openclaw', ['gateway', 'wake', '--text', text, '--mode', 'now'], {\n stdio: 'inherit'\n });\n } catch (err: any) {\n if (err?.code === 'ENOENT') {\n throw new Error('Urgent wake failed: openclaw CLI not found.');\n }\n throw new Error(`Urgent wake failed: ${err?.message || 'unknown error'}`);\n }\n}\n\nexport async function flush(): Promise<CheckpointData | null> {\n if (pendingCheckpoint) {\n clearTimeout(pendingCheckpoint);\n pendingCheckpoint = null;\n }\n if (!pendingData) return null;\n\n const { dir, data } = pendingData;\n pendingData = null;\n writeCheckpointToDisk(dir, data);\n return data;\n}\n\nexport async function checkpoint(options: CheckpointOptions): Promise<CheckpointData> {\n const dir = ensureClawvaultDir(options.vaultPath);\n \n const data: CheckpointData = {\n timestamp: new Date().toISOString(),\n workingOn: options.workingOn || null,\n focus: options.focus || null,\n blocked: options.blocked || null,\n urgent: options.urgent || false\n };\n \n const sessionState = loadSessionState(dir);\n const envState = getEnvSessionState();\n data.sessionId = sessionState?.sessionId;\n data.sessionKey = envState.sessionKey || sessionState?.sessionKey || sessionState?.sessionId;\n data.model = envState.model || sessionState?.model;\n data.tokenEstimate = envState.tokenEstimate ?? sessionState?.tokenEstimate;\n data.sessionStartedAt = sessionState?.startedAt;\n\n if (options.urgent) {\n if (pendingCheckpoint) {\n clearTimeout(pendingCheckpoint);\n pendingCheckpoint = null;\n }\n pendingData = null;\n writeCheckpointToDisk(dir, data);\n triggerUrgentWake(data);\n } else {\n // Debounce writes to avoid rapid write spam; last call wins.\n pendingData = { dir, data };\n if (pendingCheckpoint) clearTimeout(pendingCheckpoint);\n pendingCheckpoint = setTimeout(() => {\n void flush();\n }, 1000);\n }\n\n return data;\n}\n\nexport async function clearDirtyFlag(vaultPath: string): Promise<void> {\n const flagPath = path.join(vaultPath, CLAWVAULT_DIR, DIRTY_DEATH_FLAG);\n if (fs.existsSync(flagPath)) {\n fs.unlinkSync(flagPath);\n }\n}\n\n// Alias for CLI ergonomics (`clawvault clean-exit`)\nexport async function cleanExit(vaultPath: string): Promise<void> {\n await clearDirtyFlag(vaultPath);\n}\n\nexport async function checkDirtyDeath(vaultPath: string): Promise<{\n died: boolean;\n checkpoint: CheckpointData | null;\n deathTime: string | null;\n}> {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n const flagPath = path.join(dir, DIRTY_DEATH_FLAG);\n const checkpointPath = path.join(dir, CHECKPOINT_FILE);\n \n if (!fs.existsSync(flagPath)) {\n return { died: false, checkpoint: null, deathTime: null };\n }\n \n const deathTime = fs.readFileSync(flagPath, 'utf-8').trim();\n \n let checkpoint: CheckpointData | null = null;\n if (fs.existsSync(checkpointPath)) {\n try {\n checkpoint = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));\n } catch {\n // Ignore parse errors\n }\n }\n \n return { died: true, checkpoint, deathTime };\n}\n\nexport async function setSessionState(vaultPath: string, session: string | SessionState): Promise<void> {\n const dir = ensureClawvaultDir(vaultPath);\n const sessionStatePath = path.join(dir, SESSION_STATE_FILE);\n \n const state: SessionState = typeof session === 'string'\n ? { sessionId: session }\n : { ...session };\n\n if (!state.startedAt) {\n state.startedAt = new Date().toISOString();\n }\n\n fs.writeFileSync(sessionStatePath, JSON.stringify(state, null, 2));\n}\n",364 "inputSchema": {},365 "outputSchema": null,366 "icons": null,367 "annotations": null,368 "meta": null,369 "execution": null370 },371 {372 "name": "doctor.ts",373 "title": null,374 "description": "Script: doctor.ts. Code:\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { ClawVault, findVault } from '../lib/vault.js';\nimport { scanVaultLinks } from '../lib/backlinks.js';\nimport { formatAge } from '../lib/time.js';\nimport { hasQmd } from '../lib/search.js';\n\nconst CLAWVAULT_DIR = '.clawvault';\nconst CHECKPOINT_FILE = 'last-checkpoint.json';\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst ACTIVE_USE_DAYS = 7;\n\nexport type DoctorStatus = 'ok' | 'warn' | 'error';\n\nexport interface DoctorCheck {\n label: string;\n status: DoctorStatus;\n detail?: string;\n hint?: string;\n}\n\nexport interface DoctorReport {\n vaultPath?: string;\n checks: DoctorCheck[];\n warnings: number;\n errors: number;\n}\n\nfunction daysSince(date: Date, now: number = Date.now()): number {\n return Math.max(0, Math.floor((now - date.getTime()) / DAY_MS));\n}\n\nfunction describeAge(date: Date, now: number = Date.now()): string {\n return formatAge(now - date.getTime());\n}\n\nfunction loadCheckpointTimestamp(vaultPath: string): { timestamp?: string; error?: string } {\n const checkpointPath = path.join(vaultPath, CLAWVAULT_DIR, CHECKPOINT_FILE);\n if (!fs.existsSync(checkpointPath)) {\n return {};\n }\n try {\n const data = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8')) as { timestamp?: string };\n return { timestamp: data.timestamp };\n } catch (err: any) {\n return { error: err?.message || 'Failed to parse checkpoint' };\n }\n}\n\nfunction getShellConfigPaths(shellPath: string | undefined): string[] {\n const home = os.homedir();\n const shellName = shellPath ? path.basename(shellPath) : 'bash';\n if (shellName === 'zsh') {\n return [path.join(home, '.zshrc'), path.join(home, '.zprofile')];\n }\n if (shellName === 'fish') {\n return [path.join(home, '.config', 'fish', 'config.fish')];\n }\n return [path.join(home, '.bashrc'), path.join(home, '.bash_profile'), path.join(home, '.profile')];\n}\n\nfunction hasClawvaultPathConfig(paths: string[]): boolean {\n for (const filePath of paths) {\n if (!fs.existsSync(filePath)) continue;\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n if (/CLAWVAULT_PATH\\s*=/.test(content)) {\n return true;\n }\n } catch {\n // ignore unreadable config files\n }\n }\n return false;\n}\n\nasync function resolveVault(vaultPath?: string): Promise<ClawVault> {\n if (vaultPath) {\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n return vault;\n }\n\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n const vault = new ClawVault(path.resolve(envPath));\n await vault.load();\n return vault;\n }\n\n const found = await findVault();\n if (!found) {\n throw new Error('No ClawVault found. Run `clawvault init` first.');\n }\n return found;\n}\n\nexport async function doctor(vaultPath?: string): Promise<DoctorReport> {\n const checks: DoctorCheck[] = [];\n let warnings = 0;\n let errors = 0;\n\n if (hasQmd()) {\n checks.push({ label: 'qmd installed', status: 'ok' });\n } else {\n checks.push({\n label: 'qmd installed',\n status: 'error',\n hint: 'Install qmd to enable ClawVault commands.'\n });\n errors++;\n }\n\n const shellConfigs = getShellConfigPaths(process.env.SHELL).filter(fs.existsSync);\n if (hasClawvaultPathConfig(shellConfigs)) {\n checks.push({\n label: 'CLAWVAULT_PATH in shell config',\n status: 'ok',\n detail: shellConfigs.map(p => path.basename(p)).join(', ')\n });\n } else {\n checks.push({\n label: 'CLAWVAULT_PATH in shell config',\n status: 'warn',\n hint: 'Run `clawvault shell-init` and add it to your shell rc.'\n });\n warnings++;\n }\n\n if (!hasQmd()) {\n return { vaultPath, checks, warnings, errors };\n }\n\n let vault: ClawVault;\n try {\n vault = await resolveVault(vaultPath);\n checks.push({ label: 'vault found', status: 'ok', detail: vault.getPath() });\n } catch (err: any) {\n checks.push({\n label: 'vault found',\n status: 'error',\n detail: err?.message || 'Unable to locate vault'\n });\n errors++;\n return { vaultPath, checks, warnings, errors };\n }\n\n const stats = await vault.stats();\n const documents = await vault.list();\n const handoffs = await vault.list('handoffs');\n const inbox = await vault.list('inbox');\n const qmdCollection = vault.getQmdCollection();\n\n if (qmdCollection) {\n checks.push({ label: 'qmd collection configured', status: 'ok', detail: qmdCollection });\n } else {\n checks.push({\n label: 'qmd collection configured',\n status: 'warn',\n hint: 'Set qmd collection in .clawvault.json'\n });\n warnings++;\n }\n\n const latestDoc = documents\n .slice()\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())[0];\n const latestDocAge = latestDoc ? daysSince(latestDoc.modified) : null;\n\n let lastHandoffAge: number | null = null;\n if (handoffs.length === 0) {\n checks.push({\n label: 'recent handoff',\n status: 'warn',\n hint: 'Run `clawvault sleep` at the end of sessions.'\n });\n warnings++;\n } else {\n const latestHandoff = handoffs\n .slice()\n .sort((a, b) => b.modified.getTime() - a.modified.getTime())[0];\n lastHandoffAge = daysSince(latestHandoff.modified);\n const ageLabel = describeAge(latestHandoff.modified);\n if (lastHandoffAge > 1) {\n checks.push({\n label: 'recent handoff',\n status: 'warn',\n detail: `Last handoff ${ageLabel} ago`,\n hint: 'Run `clawvault sleep` before long pauses.'\n });\n warnings++;\n } else {\n checks.push({\n label: 'recent handoff',\n status: 'ok',\n detail: `Last handoff ${ageLabel} ago`\n });\n }\n }\n\n const checkpointInfo = loadCheckpointTimestamp(vault.getPath());\n const activeUse =\n (latestDocAge !== null && latestDocAge <= ACTIVE_USE_DAYS) ||\n (lastHandoffAge !== null && lastHandoffAge <= ACTIVE_USE_DAYS);\n\n if (checkpointInfo.error) {\n checks.push({\n label: 'checkpoint freshness',\n status: 'warn',\n detail: checkpointInfo.error\n });\n warnings++;\n } else if (!checkpointInfo.timestamp) {\n const status = activeUse ? 'warn' : 'ok';\n if (status === 'warn') warnings++;\n checks.push({\n label: 'checkpoint freshness',\n status,\n detail: activeUse ? 'No checkpoint found' : 'No checkpoint found (vault appears inactive)',\n hint: activeUse ? 'Run `clawvault checkpoint` during heavy work.' : undefined\n });\n } else {\n const checkpointDate = new Date(checkpointInfo.timestamp);\n const checkpointAge = daysSince(checkpointDate);\n const ageLabel = describeAge(checkpointDate);\n if (activeUse && checkpointAge > 1) {\n checks.push({\n label: 'checkpoint freshness',\n status: 'warn',\n detail: `Last checkpoint ${ageLabel} ago`,\n hint: 'Checkpoint at least once per active day.'\n });\n warnings++;\n } else {\n checks.push({\n label: 'checkpoint freshness',\n status: 'ok',\n detail: `Last checkpoint ${ageLabel} ago`\n });\n }\n }\n\n const linkScan = scanVaultLinks(vault.getPath());\n if (linkScan.orphans.length > 20) {\n checks.push({\n label: 'orphan links',\n status: 'warn',\n detail: `${linkScan.orphans.length} orphan link(s)`,\n hint: 'Run `clawvault link --orphans` to review.'\n });\n warnings++;\n } else {\n checks.push({\n label: 'orphan links',\n status: 'ok',\n detail: `${linkScan.orphans.length} orphan link(s)`\n });\n }\n\n if (inbox.length > 5) {\n checks.push({\n label: 'inbox backlog',\n status: 'warn',\n detail: `${inbox.length} inbox item(s) pending`,\n hint: 'Process inbox items to keep memory tidy.'\n });\n warnings++;\n } else {\n checks.push({\n label: 'inbox backlog',\n status: 'ok',\n detail: `${inbox.length} inbox item(s) pending`\n });\n }\n\n if (stats.documents < 5) {\n checks.push({\n label: 'vault activity',\n status: 'warn',\n detail: `${stats.documents} total documents`,\n hint: 'Start capturing decisions, lessons, and projects.'\n });\n warnings++;\n }\n\n return { vaultPath: vault.getPath(), checks, warnings, errors };\n}\n",375 "inputSchema": {},376 "outputSchema": null,377 "icons": null,378 "annotations": null,379 "meta": null,380 "execution": null381 },382 {383 "name": "recover.test.ts",384 "title": null,385 "description": "Script: recover.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { checkDirtyDeathMock, clearDirtyFlagMock } = vi.hoisted(() => ({\n checkDirtyDeathMock: vi.fn(),\n clearDirtyFlagMock: vi.fn()\n}));\n\nvi.mock('./checkpoint.js', () => ({\n checkDirtyDeath: checkDirtyDeathMock,\n clearDirtyFlag: clearDirtyFlagMock\n}));\n\nimport { formatRecoveryInfo, recover } from './recover.js';\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-recover-'));\n}\n\nafterEach(() => {\n vi.clearAllMocks();\n});\n\ndescribe('recover', () => {\n it('returns clean startup info when no death is detected', async () => {\n checkDirtyDeathMock.mockResolvedValue({\n died: false,\n checkpoint: null,\n deathTime: null\n });\n\n const info = await recover('/tmp/vault');\n expect(info.died).toBe(false);\n expect(info.recoveryMessage).toBe('No context death detected. Clean startup.');\n expect(clearDirtyFlagMock).not.toHaveBeenCalled();\n });\n\n it('returns the latest handoff and clears the flag when requested', async () => {\n checkDirtyDeathMock.mockResolvedValue({\n died: true,\n deathTime: '2024-01-01T00:00:00Z',\n checkpoint: {\n timestamp: '2024-01-01T00:00:00Z',\n workingOn: 'feature',\n focus: 'tests',\n blocked: null\n }\n });\n\n const vaultPath = makeTempVaultDir();\n try {\n const handoffsDir = path.join(vaultPath, 'handoffs');\n fs.mkdirSync(handoffsDir, { recursive: true });\n fs.writeFileSync(path.join(handoffsDir, 'handoff-2024-01-01.md'), 'old handoff');\n fs.writeFileSync(path.join(handoffsDir, 'handoff-2024-01-02.md'), 'latest handoff');\n\n const info = await recover(vaultPath, { clearFlag: true });\n expect(info.died).toBe(true);\n expect(info.handoffPath).toBe(path.join(handoffsDir, 'handoff-2024-01-02.md'));\n expect(info.handoffContent).toBe('latest handoff');\n expect(info.recoveryMessage).toContain('CONTEXT DEATH DETECTED');\n expect(clearDirtyFlagMock).toHaveBeenCalledWith(vaultPath);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n});\n\ndescribe('formatRecoveryInfo', () => {\n it('includes verbose checkpoint and handoff content when requested', () => {\n const info = {\n died: true,\n deathTime: '2024-01-01T00:00:00Z',\n checkpoint: {\n timestamp: '2024-01-01T00:00:00Z',\n workingOn: 'feature',\n focus: 'tests',\n blocked: null,\n sessionKey: 'key',\n model: 'model',\n tokenEstimate: 100\n },\n handoffPath: '/tmp/vault/handoffs/handoff-2024-01-01.md',\n handoffContent: 'handoff text',\n recoveryMessage: 'message'\n };\n\n const output = formatRecoveryInfo(info, { verbose: true });\n expect(output).toContain('Checkpoint JSON:');\n expect(output).toContain('\"sessionKey\": \"key\"');\n expect(output).toContain('Handoff content:');\n expect(output).toContain('handoff text');\n });\n});\n",386 "inputSchema": {},387 "outputSchema": null,388 "icons": null,389 "annotations": null,390 "meta": null,391 "execution": null392 },393 {394 "name": "link.test.ts",395 "title": null,396 "description": "Script: link.test.ts. Code:\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { linkCommand } from './link.js';\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-link-'));\n}\n\nfunction writeFile(root: string, relative: string, content: string): void {\n const filePath = path.join(root, relative);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, content);\n}\n\ndescribe('link command', () => {\n let vaultPath = '';\n let originalEnv: string | undefined;\n\n beforeEach(() => {\n vaultPath = makeTempVaultDir();\n originalEnv = process.env.CLAWVAULT_PATH;\n process.env.CLAWVAULT_PATH = vaultPath;\n });\n\n afterEach(() => {\n if (originalEnv === undefined) {\n delete process.env.CLAWVAULT_PATH;\n } else {\n process.env.CLAWVAULT_PATH = originalEnv;\n }\n fs.rmSync(vaultPath, { recursive: true, force: true });\n vi.restoreAllMocks();\n });\n\n it('rebuilds backlinks and shows backlinks for a target', async () => {\n writeFile(vaultPath, 'people/alice.md', '# Alice');\n writeFile(vaultPath, 'notes/a.md', 'Met with [[people/alice]].');\n writeFile(vaultPath, 'notes/b.md', 'Followed up with [[people/alice]].');\n\n const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});\n\n await linkCommand(undefined, { rebuild: true });\n\n const backlinksPath = path.join(vaultPath, '.clawvault', 'backlinks.json');\n expect(fs.existsSync(backlinksPath)).toBe(true);\n\n logSpy.mockClear();\n await linkCommand(undefined, { backlinks: 'people/alice' });\n\n const output = logSpy.mock.calls.map(call => call.join(' ')).join('\\n');\n expect(output).toContain('Backlinks \u2192 people/alice');\n expect(output).toContain('notes/a');\n expect(output).toContain('notes/b');\n });\n\n it('lists orphan links', async () => {\n writeFile(vaultPath, 'notes/a.md', 'Reference to [[missing]].');\n\n const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});\n await linkCommand(undefined, { orphans: true });\n\n const output = logSpy.mock.calls.map(call => call.join(' ')).join('\\n');\n expect(output).toContain('orphan link(s) found');\n expect(output).toContain('[[missing]]');\n });\n});\n",397 "inputSchema": {},398 "outputSchema": null,399 "icons": null,400 "annotations": null,401 "meta": null,402 "execution": null403 },404 {405 "name": "status.ts",406 "title": null,407 "description": "Script: status.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { execFileSync } from 'child_process';\nimport { ClawVault } from '../lib/vault.js';\nimport { hasQmd, QmdUnavailableError } from '../lib/search.js';\nimport { formatAge } from '../lib/time.js';\nimport { scanVaultLinks } from '../lib/backlinks.js';\nimport type { CheckpointData } from './checkpoint.js';\n\nexport interface VaultStatus {\n vaultName: string;\n vaultPath: string;\n health: 'ok' | 'warning';\n issues: string[];\n checkpoint: {\n exists: boolean;\n timestamp?: string;\n age?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n };\n qmd: {\n collection: string;\n root: string;\n indexStatus: 'present' | 'missing' | 'root-mismatch';\n error?: string;\n };\n git?: {\n repoRoot: string;\n clean: boolean;\n dirtyCount: number;\n };\n links: {\n total: number;\n orphans: number;\n };\n documents: number;\n categories: Record<string, number>;\n}\n\nconst CLAWVAULT_DIR = '.clawvault';\nconst CHECKPOINT_FILE = 'last-checkpoint.json';\nconst DIRTY_DEATH_FLAG = 'dirty-death.flag';\n\nfunction findGitRoot(startPath: string): string | null {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, '.git'))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nfunction getGitStatus(repoRoot: string): { clean: boolean; dirtyCount: number } {\n const output = execFileSync('git', ['-C', repoRoot, 'status', '--porcelain'], {\n encoding: 'utf-8'\n });\n const lines = output.split('\\n').filter(Boolean);\n return { clean: lines.length === 0, dirtyCount: lines.length };\n}\n\n/**\n * Parse qmd collection list text output\n * Format:\n * Collections (N):\n *\n * name (qmd://name/)\n * Pattern: **\\/*.md\n * Files: 155\n * Updated: 1m ago\n */\nfunction parseQmdCollectionsText(raw: string): string[] {\n const names: string[] = [];\n // Match lines like \"memory (qmd://memory/)\"\n const regex = /^(\\S+)\\s+\\(qmd:\\/\\/\\1\\/\\)/gm;\n let match;\n while ((match = regex.exec(raw)) !== null) {\n names.push(match[1]);\n }\n return names;\n}\n\nfunction getQmdIndexStatus(collection: string, root: string): 'present' | 'missing' | 'root-mismatch' {\n // qmd collection list doesn't support --json, parse text output instead\n const output = execFileSync('qmd', ['collection', 'list'], { encoding: 'utf-8' });\n const names = parseQmdCollectionsText(output);\n \n if (names.includes(collection)) {\n return 'present';\n }\n\n return 'missing';\n}\n\nfunction loadCheckpoint(vaultPath: string): { data: CheckpointData | null; error?: string } {\n const checkpointPath = path.join(vaultPath, CLAWVAULT_DIR, CHECKPOINT_FILE);\n if (!fs.existsSync(checkpointPath)) {\n return { data: null };\n }\n try {\n const data = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8')) as CheckpointData;\n return { data };\n } catch (err: any) {\n return { data: null, error: err?.message || 'Failed to parse checkpoint' };\n }\n}\n\nexport async function getStatus(vaultPath: string): Promise<VaultStatus> {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n const stats = await vault.stats();\n const linkScan = scanVaultLinks(vault.getPath());\n\n const issues: string[] = [];\n const checkpointInfo = loadCheckpoint(vault.getPath());\n const checkpoint = checkpointInfo.data;\n\n if (checkpointInfo.error) {\n issues.push(`Checkpoint parse error: ${checkpointInfo.error}`);\n }\n\n const checkpointStatus: VaultStatus['checkpoint'] = {\n exists: Boolean(checkpoint),\n timestamp: checkpoint?.timestamp,\n age: checkpoint?.timestamp\n ? formatAge(Date.now() - new Date(checkpoint.timestamp).getTime())\n : undefined,\n sessionKey: checkpoint?.sessionKey,\n model: checkpoint?.model,\n tokenEstimate: checkpoint?.tokenEstimate\n };\n\n if (!checkpointStatus.exists) {\n issues.push('No checkpoint found');\n }\n\n const dirtyFlagPath = path.join(vault.getPath(), CLAWVAULT_DIR, DIRTY_DEATH_FLAG);\n if (fs.existsSync(dirtyFlagPath)) {\n issues.push('Dirty death flag is set');\n }\n\n const qmdCollection = vault.getQmdCollection();\n const qmdRoot = vault.getQmdRoot();\n let qmdIndexStatus: VaultStatus['qmd']['indexStatus'] = 'missing';\n let qmdError: string | undefined;\n try {\n qmdIndexStatus = getQmdIndexStatus(qmdCollection, qmdRoot);\n if (qmdIndexStatus !== 'present') {\n issues.push(`qmd collection ${qmdIndexStatus.replace('-', ' ')}`);\n }\n } catch (err: any) {\n qmdError = err?.message || 'Failed to check qmd index';\n issues.push(`qmd status error: ${qmdError}`);\n }\n\n let gitStatus: VaultStatus['git'] | undefined;\n const gitRoot = findGitRoot(vault.getPath());\n if (gitRoot) {\n try {\n const gitInfo = getGitStatus(gitRoot);\n gitStatus = { repoRoot: gitRoot, ...gitInfo };\n if (!gitInfo.clean) {\n issues.push(`Uncommitted changes: ${gitInfo.dirtyCount}`);\n }\n } catch (err: any) {\n issues.push(`Git status error: ${err?.message || 'unknown error'}`);\n }\n }\n\n return {\n vaultName: vault.getName(),\n vaultPath: vault.getPath(),\n health: issues.length === 0 ? 'ok' : 'warning',\n issues,\n checkpoint: checkpointStatus,\n qmd: {\n collection: qmdCollection,\n root: qmdRoot,\n indexStatus: qmdIndexStatus,\n error: qmdError\n },\n git: gitStatus,\n links: {\n total: linkScan.linkCount,\n orphans: linkScan.orphans.length\n },\n documents: stats.documents,\n categories: stats.categories\n };\n}\n\nexport function formatStatus(status: VaultStatus): string {\n let output = 'ClawVault Status\\n';\n output += '-'.repeat(40) + '\\n';\n output += `Vault: ${status.vaultName}\\n`;\n output += `Path: ${status.vaultPath}\\n`;\n output += `Health: ${status.health}\\n`;\n if (status.issues.length > 0) {\n output += `Issues: ${status.issues.join('; ')}\\n`;\n } else {\n output += 'Issues: none\\n';\n }\n\n output += '\\nCheckpoint:\\n';\n if (!status.checkpoint.exists) {\n output += ' - none\\n';\n } else {\n output += ` - Timestamp: ${status.checkpoint.timestamp}\\n`;\n if (status.checkpoint.age) {\n output += ` - Age: ${status.checkpoint.age}\\n`;\n }\n if (status.checkpoint.sessionKey) {\n output += ` - Session key: ${status.checkpoint.sessionKey}\\n`;\n }\n if (status.checkpoint.model) {\n output += ` - Model: ${status.checkpoint.model}\\n`;\n }\n if (status.checkpoint.tokenEstimate !== undefined) {\n output += ` - Token estimate: ${status.checkpoint.tokenEstimate}\\n`;\n }\n }\n\n output += '\\nqmd:\\n';\n output += ` - Collection: ${status.qmd.collection}\\n`;\n output += ` - Root: ${status.qmd.root}\\n`;\n output += ` - Index: ${status.qmd.indexStatus}\\n`;\n if (status.qmd.error) {\n output += ` - Error: ${status.qmd.error}\\n`;\n }\n\n if (status.git) {\n output += '\\nGit:\\n';\n output += ` - Repo: ${status.git.repoRoot}\\n`;\n output += ` - Status: ${status.git.clean ? 'clean' : 'dirty'} (${status.git.dirtyCount} change(s))\\n`;\n }\n\n output += '\\nLinks:\\n';\n output += ` - Total: ${status.links.total}\\n`;\n if (status.links.orphans > 0) {\n output += ` - Orphans: ${status.links.orphans}\\n`;\n }\n\n output += '\\nDocuments:\\n';\n output += ` - Total: ${status.documents}\\n`;\n output += ' - By category:\\n';\n for (const [category, count] of Object.entries(status.categories)) {\n output += ` * ${category}: ${count}\\n`;\n }\n\n output += '-'.repeat(40) + '\\n';\n return output;\n}\n\nexport async function statusCommand(\n vaultPath: string,\n options: { json?: boolean } = {}\n): Promise<void> {\n const status = await getStatus(vaultPath);\n if (options.json) {\n console.log(JSON.stringify(status, null, 2));\n return;\n }\n console.log(formatStatus(status));\n}\n",408 "inputSchema": {},409 "outputSchema": null,410 "icons": null,411 "annotations": null,412 "meta": null,413 "execution": null414 },415 {416 "name": "recover.ts",417 "title": null,418 "description": "Script: recover.ts. Code:\n/**\n * Recovery command - detect dirty death and provide recovery info\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { checkDirtyDeath, clearDirtyFlag, CheckpointData } from './checkpoint.js';\nimport { formatAge } from '../lib/time.js';\n\nexport interface RecoveryInfo {\n died: boolean;\n deathTime: string | null;\n checkpoint: CheckpointData | null;\n handoffPath: string | null;\n handoffContent: string | null;\n recoveryMessage: string;\n}\n\nexport async function recover(\n vaultPath: string,\n options: { clearFlag?: boolean; verbose?: boolean } = {}\n): Promise<RecoveryInfo> {\n const { clearFlag = false } = options;\n const { died, checkpoint, deathTime } = await checkDirtyDeath(vaultPath);\n \n if (!died) {\n return {\n died: false,\n deathTime: null,\n checkpoint: null,\n handoffPath: null,\n handoffContent: null,\n recoveryMessage: 'No context death detected. Clean startup.'\n };\n }\n \n // Find most recent handoff\n const handoffsDir = path.join(vaultPath, 'handoffs');\n let handoffPath: string | null = null;\n let handoffContent: string | null = null;\n \n if (fs.existsSync(handoffsDir)) {\n const files = fs.readdirSync(handoffsDir)\n .filter(f => f.startsWith('handoff-') && f.endsWith('.md'))\n .sort()\n .reverse();\n \n if (files.length > 0) {\n handoffPath = path.join(handoffsDir, files[0]);\n handoffContent = fs.readFileSync(handoffPath, 'utf-8');\n }\n }\n \n // Build recovery message\n let message = '\u26a0\ufe0f **CONTEXT DEATH DETECTED**\\n\\n';\n message += `Your previous session died at ${deathTime}.\\n\\n`;\n \n if (checkpoint) {\n message += '**Last known state:**\\n';\n if (checkpoint.workingOn) {\n message += `- Working on: ${checkpoint.workingOn}\\n`;\n }\n if (checkpoint.focus) {\n message += `- Focus: ${checkpoint.focus}\\n`;\n }\n if (checkpoint.blocked) {\n message += `- Blocked: ${checkpoint.blocked}\\n`;\n }\n message += '\\n';\n }\n \n if (handoffPath) {\n message += `**Last handoff:** ${path.basename(handoffPath)}\\n`;\n message += 'Review and resume from where you left off.\\n';\n } else {\n message += '**No handoff found.** You may have lost context.\\n';\n }\n \n // Clear the flag if requested\n if (clearFlag) {\n await clearDirtyFlag(vaultPath);\n }\n \n return {\n died: true,\n deathTime,\n checkpoint,\n handoffPath,\n handoffContent,\n recoveryMessage: message\n };\n}\n\n/**\n * Format recovery info for CLI output\n */\nexport function formatRecoveryInfo(info: RecoveryInfo, options: { verbose?: boolean } = {}): string {\n const { verbose = false } = options;\n if (!info.died) {\n return '\u2713 Clean startup - no context death detected.';\n }\n \n let output = '\\n\u26a0\ufe0f CONTEXT DEATH DETECTED\\n';\n output += '\u2550'.repeat(40) + '\\n\\n';\n output += `Death time: ${info.deathTime}\\n`;\n if (info.checkpoint?.timestamp) {\n const age = formatAge(Date.now() - new Date(info.checkpoint.timestamp).getTime());\n output += `Checkpoint: ${info.checkpoint.timestamp} (${age} ago)\\n`;\n }\n output += '\\n';\n \n if (info.checkpoint) {\n output += 'Last checkpoint:\\n';\n if (info.checkpoint.workingOn) {\n output += ` \u2022 Working on: ${info.checkpoint.workingOn}\\n`;\n }\n if (info.checkpoint.focus) {\n output += ` \u2022 Focus: ${info.checkpoint.focus}\\n`;\n }\n if (info.checkpoint.blocked) {\n output += ` \u2022 Blocked: ${info.checkpoint.blocked}\\n`;\n }\n if (info.checkpoint.sessionKey || info.checkpoint.model || info.checkpoint.tokenEstimate !== undefined) {\n output += ' \u2022 Session:\\n';\n if (info.checkpoint.sessionKey) {\n output += ` - Key: ${info.checkpoint.sessionKey}\\n`;\n }\n if (info.checkpoint.model) {\n output += ` - Model: ${info.checkpoint.model}\\n`;\n }\n if (info.checkpoint.tokenEstimate !== undefined) {\n output += ` - Token estimate: ${info.checkpoint.tokenEstimate}\\n`;\n }\n }\n output += '\\n';\n } else {\n output += 'No checkpoint data found.\\n\\n';\n }\n \n if (info.handoffPath) {\n output += `Last handoff: ${path.basename(info.handoffPath)}\\n`;\n } else {\n output += 'No handoff found - context may be lost.\\n';\n }\n \n if (verbose) {\n if (info.checkpoint) {\n output += '\\nCheckpoint JSON:\\n';\n output += JSON.stringify(info.checkpoint, null, 2) + '\\n';\n }\n if (info.handoffContent) {\n output += '\\nHandoff content:\\n';\n output += info.handoffContent.trim() + '\\n';\n }\n }\n\n output += '\\n' + '\u2550'.repeat(40) + '\\n';\n output += 'Run `clawvault recap` to see full context.\\n';\n \n return output;\n}\n",419 "inputSchema": {},420 "outputSchema": null,421 "icons": null,422 "annotations": null,423 "meta": null,424 "execution": null425 },426 {427 "name": "setup.test.ts",428 "title": null,429 "description": "Script: setup.test.ts. Code:\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { hasQmdMock } = vi.hoisted(() => ({\n hasQmdMock: vi.fn()\n}));\n\nvi.mock('../lib/search.js', async () => {\n const actual = await vi.importActual<typeof import('../lib/search.js')>('../lib/search.js');\n return {\n ...actual,\n hasQmd: hasQmdMock\n };\n});\n\nimport { setupCommand } from './setup.js';\n\ndescribe('setup command', () => {\n let baseDir: string;\n let vaultPath: string;\n\n beforeEach(() => {\n baseDir = fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-setup-'));\n vaultPath = path.join(baseDir, 'vault');\n process.env.CLAWVAULT_PATH = vaultPath;\n });\n\n afterEach(() => {\n delete process.env.CLAWVAULT_PATH;\n fs.rmSync(baseDir, { recursive: true, force: true });\n vi.clearAllMocks();\n });\n\n it('creates a vault at CLAWVAULT_PATH when set', async () => {\n hasQmdMock.mockReturnValue(false);\n // Ensure the path doesn't exist before setup\n expect(fs.existsSync(vaultPath)).toBe(false);\n await setupCommand();\n // CLAWVAULT_PATH should be used even if OpenClaw default exists\n expect(fs.existsSync(vaultPath)).toBe(true);\n expect(fs.existsSync(path.join(vaultPath, '.clawvault.json'))).toBe(true);\n expect(fs.existsSync(path.join(vaultPath, 'inbox'))).toBe(true);\n });\n});\n",430 "inputSchema": {},431 "outputSchema": null,432 "icons": null,433 "annotations": null,434 "meta": null,435 "execution": null436 },437 {438 "name": "repair-session.test.ts",439 "title": null,440 "description": "Script: repair-session.test.ts. Code:\n/**\n * Tests for session repair functionality\n */\n\nimport { describe, it, expect, beforeEach, afterEach } from 'vitest';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n parseTranscript,\n extractToolUses,\n findCorruptedEntries,\n computeParentRelinks,\n analyzeSession,\n repairSession,\n type TranscriptEntry\n} from '../lib/session-repair.js';\n\n// Test fixtures\nconst CLEAN_SESSION = [\n { type: 'session', version: 3, id: 'test-session-clean', timestamp: '2026-01-01T00:00:00.000Z' },\n { type: 'message', id: 'msg-1', parentId: null, timestamp: '2026-01-01T00:00:01.000Z', message: { role: 'user', content: [{ type: 'text', text: 'Hello' }] } },\n { type: 'message', id: 'msg-2', parentId: 'msg-1', timestamp: '2026-01-01T00:00:02.000Z', message: { role: 'assistant', content: [{ type: 'text', text: 'Hi there!' }, { type: 'toolCall', id: 'toolu_123', name: 'exec', arguments: { command: 'ls' } }], stopReason: 'toolUse' } },\n { type: 'message', id: 'msg-3', parentId: 'msg-2', timestamp: '2026-01-01T00:00:03.000Z', message: { role: 'toolResult', toolCallId: 'toolu_123', content: [{ type: 'text', text: 'file1.txt\\nfile2.txt' }] } },\n { type: 'message', id: 'msg-4', parentId: 'msg-3', timestamp: '2026-01-01T00:00:04.000Z', message: { role: 'assistant', content: [{ type: 'text', text: 'Found 2 files.' }], stopReason: 'stop' } }\n];\n\nconst CORRUPTED_SESSION = [\n { type: 'session', version: 3, id: 'test-session-corrupted', timestamp: '2026-01-01T00:00:00.000Z' },\n { type: 'message', id: 'msg-1', parentId: null, timestamp: '2026-01-01T00:00:01.000Z', message: { role: 'user', content: [{ type: 'text', text: 'Hello' }] } },\n // Aborted tool call with partialJson\n { type: 'message', id: 'msg-2', parentId: 'msg-1', timestamp: '2026-01-01T00:00:02.000Z', message: { role: 'assistant', content: [{ type: 'toolCall', id: 'toolu_aborted', name: 'exec', arguments: { command: 'long' }, partialJson: '{\"command\": \"long' }], stopReason: 'aborted' } },\n // Orphaned tool result referencing aborted call\n { type: 'message', id: 'msg-3', parentId: 'msg-2', timestamp: '2026-01-01T00:00:03.000Z', message: { role: 'toolResult', toolCallId: 'toolu_aborted', content: [{ type: 'text', text: 'synthetic error' }], isError: true } },\n // Next valid message that needs relinking\n { type: 'message', id: 'msg-4', parentId: 'msg-3', timestamp: '2026-01-01T00:00:04.000Z', message: { role: 'user', content: [{ type: 'text', text: 'What happened?' }] } }\n];\n\nconst ORPHAN_ONLY_SESSION = [\n { type: 'session', version: 3, id: 'test-session-orphan', timestamp: '2026-01-01T00:00:00.000Z' },\n { type: 'message', id: 'msg-1', parentId: null, timestamp: '2026-01-01T00:00:01.000Z', message: { role: 'user', content: [{ type: 'text', text: 'Hello' }] } },\n // Orphaned tool result with no matching tool call at all\n { type: 'message', id: 'msg-2', parentId: 'msg-1', timestamp: '2026-01-01T00:00:02.000Z', message: { role: 'toolResult', toolCallId: 'toolu_nonexistent', content: [{ type: 'text', text: 'phantom result' }] } },\n { type: 'message', id: 'msg-3', parentId: 'msg-2', timestamp: '2026-01-01T00:00:03.000Z', message: { role: 'assistant', content: [{ type: 'text', text: 'Continuing...' }] } }\n];\n\nfunction createTempSession(entries: unknown[]): string {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-test-'));\n const filePath = path.join(tmpDir, 'test-session.jsonl');\n const content = entries.map(e => JSON.stringify(e)).join('\\n') + '\\n';\n fs.writeFileSync(filePath, content);\n return filePath;\n}\n\nfunction cleanupTempSession(filePath: string): void {\n const dir = path.dirname(filePath);\n fs.rmSync(dir, { recursive: true, force: true });\n}\n\ndescribe('parseTranscript', () => {\n it('parses valid JSONL file', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const entries = parseTranscript(filePath);\n expect(entries).toHaveLength(5);\n expect(entries[0].entry.type).toBe('session');\n expect(entries[1].entry.id).toBe('msg-1');\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('extractToolUses', () => {\n it('extracts tool_use IDs from assistant messages', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n \n expect(toolUses.size).toBe(1);\n expect(toolUses.has('toolu_123')).toBe(true);\n \n const info = toolUses.get('toolu_123')!;\n expect(info.name).toBe('exec');\n expect(info.isAborted).toBe(false);\n expect(info.isPartial).toBe(false);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('marks aborted tool calls correctly', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n \n expect(toolUses.size).toBe(1);\n expect(toolUses.has('toolu_aborted')).toBe(true);\n \n const info = toolUses.get('toolu_aborted')!;\n expect(info.isAborted).toBe(true);\n expect(info.isPartial).toBe(true);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('findCorruptedEntries', () => {\n it('finds no corruption in clean session', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n \n expect(corrupted).toHaveLength(0);\n expect(entriesToRemove.size).toBe(0);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('finds aborted tool_use and orphaned tool_result', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n \n expect(corrupted).toHaveLength(2);\n expect(corrupted[0].type).toBe('aborted_tool_use');\n expect(corrupted[1].type).toBe('orphaned_tool_result');\n expect(entriesToRemove.size).toBe(2);\n expect(entriesToRemove.has('msg-2')).toBe(true);\n expect(entriesToRemove.has('msg-3')).toBe(true);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('finds orphaned tool_result without any matching tool_use', () => {\n const filePath = createTempSession(ORPHAN_ONLY_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n \n expect(corrupted).toHaveLength(1);\n expect(corrupted[0].type).toBe('orphaned_tool_result');\n expect(corrupted[0].toolUseId).toBe('toolu_nonexistent');\n expect(entriesToRemove.size).toBe(1);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('computeParentRelinks', () => {\n it('computes correct parent relinks', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const entries = parseTranscript(filePath);\n const toolUses = extractToolUses(entries);\n const { entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const relinks = computeParentRelinks(entries, entriesToRemove);\n \n // msg-4 should be relinked from msg-3 to msg-1\n expect(relinks).toHaveLength(1);\n expect(relinks[0].entryId).toBe('msg-4');\n expect(relinks[0].oldParentId).toBe('msg-3');\n expect(relinks[0].newParentId).toBe('msg-1');\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('analyzeSession', () => {\n it('returns clean result for clean session', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const result = analyzeSession(filePath);\n \n expect(result.sessionId).toBe('test-session-clean');\n expect(result.corruptedEntries).toHaveLength(0);\n expect(result.parentRelinks).toHaveLength(0);\n expect(result.removedCount).toBe(0);\n expect(result.repaired).toBe(false);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('detects corruption in corrupted session', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const result = analyzeSession(filePath);\n \n expect(result.sessionId).toBe('test-session-corrupted');\n expect(result.corruptedEntries).toHaveLength(2);\n expect(result.parentRelinks).toHaveLength(1);\n expect(result.removedCount).toBe(2);\n expect(result.repaired).toBe(false);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n\ndescribe('repairSession', () => {\n it('does not modify clean session', () => {\n const filePath = createTempSession(CLEAN_SESSION);\n try {\n const result = repairSession(filePath, { backup: false });\n \n expect(result.repaired).toBe(false);\n expect(result.removedCount).toBe(0);\n \n // Verify file unchanged\n const entries = parseTranscript(filePath);\n expect(entries).toHaveLength(5);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('repairs corrupted session', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const result = repairSession(filePath, { backup: false });\n \n expect(result.repaired).toBe(true);\n expect(result.removedCount).toBe(2);\n expect(result.relinkedCount).toBe(1);\n \n // Verify file was repaired\n const entries = parseTranscript(filePath);\n expect(entries).toHaveLength(3); // session + msg-1 + msg-4\n \n // Check msg-4 was relinked to msg-1\n const msg4 = entries.find(e => e.entry.id === 'msg-4');\n expect(msg4?.entry.parentId).toBe('msg-1');\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('creates backup when requested', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n try {\n const result = repairSession(filePath, { backup: true });\n \n expect(result.backupPath).toBeDefined();\n expect(fs.existsSync(result.backupPath!)).toBe(true);\n \n // Backup should contain original content\n const backupEntries = parseTranscript(result.backupPath!);\n expect(backupEntries).toHaveLength(5);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n\n it('dry-run mode does not modify file', () => {\n const filePath = createTempSession(CORRUPTED_SESSION);\n const originalContent = fs.readFileSync(filePath, 'utf-8');\n \n try {\n const result = repairSession(filePath, { backup: false, dryRun: true });\n \n expect(result.repaired).toBe(false);\n expect(result.corruptedEntries).toHaveLength(2);\n \n // File should be unchanged\n const currentContent = fs.readFileSync(filePath, 'utf-8');\n expect(currentContent).toBe(originalContent);\n } finally {\n cleanupTempSession(filePath);\n }\n });\n});\n",441 "inputSchema": {},442 "outputSchema": null,443 "icons": null,444 "annotations": null,445 "meta": null,446 "execution": null447 },448 {449 "name": "status.test.ts",450 "title": null,451 "description": "Script: status.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { execFileSyncMock, hasQmdMock } = vi.hoisted(() => ({\n execFileSyncMock: vi.fn(),\n hasQmdMock: vi.fn()\n}));\n\nlet mockStats = { documents: 0, categories: {} as Record<string, number> };\nlet mockCollection = 'vault';\nlet mockRoot = '';\n\nvi.mock('child_process', () => ({\n execFileSync: execFileSyncMock\n}));\n\nvi.mock('../lib/search.js', async () => {\n const actual = await vi.importActual<typeof import('../lib/search.js')>('../lib/search.js');\n return {\n ...actual,\n hasQmd: hasQmdMock\n };\n});\n\nvi.mock('../lib/vault.js', () => ({\n ClawVault: class {\n private vaultPath: string;\n\n constructor(vaultPath: string) {\n this.vaultPath = vaultPath;\n }\n\n async load(): Promise<void> {\n return;\n }\n\n async stats(): Promise<{ documents: number; categories: Record<string, number> }> {\n return mockStats;\n }\n\n getPath(): string {\n return this.vaultPath;\n }\n\n getName(): string {\n return mockCollection;\n }\n\n getQmdCollection(): string {\n return mockCollection;\n }\n\n getQmdRoot(): string {\n return mockRoot || this.vaultPath;\n }\n }\n}));\n\nimport { getStatus, formatStatus } from './status.js';\nimport { QmdUnavailableError } from '../lib/search.js';\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-status-'));\n}\n\nafterEach(() => {\n vi.clearAllMocks();\n});\n\ndescribe('status command', () => {\n it('throws when qmd is unavailable', async () => {\n hasQmdMock.mockReturnValue(false);\n await expect(getStatus('/tmp/vault')).rejects.toBeInstanceOf(QmdUnavailableError);\n });\n\n it('reports issues when checkpoint is missing and git/qmd are dirty', async () => {\n hasQmdMock.mockReturnValue(true);\n execFileSyncMock.mockImplementation((command: string) => {\n if (command === 'qmd') {\n return JSON.stringify([{ name: 'other', root: '/somewhere' }]);\n }\n if (command === 'git') {\n return ' M file.md\\n?? new.md\\n';\n }\n return '';\n });\n\n const vaultPath = makeTempVaultDir();\n try {\n fs.mkdirSync(path.join(vaultPath, '.git'), { recursive: true });\n const clawvaultDir = path.join(vaultPath, '.clawvault');\n fs.mkdirSync(clawvaultDir, { recursive: true });\n fs.writeFileSync(path.join(clawvaultDir, 'dirty-death.flag'), '2024-01-01T00:00:00Z');\n\n mockStats = { documents: 2, categories: { inbox: 2 } };\n mockCollection = 'vault';\n mockRoot = vaultPath;\n\n const status = await getStatus(vaultPath);\n expect(status.health).toBe('warning');\n expect(status.issues).toEqual(\n expect.arrayContaining([\n 'No checkpoint found',\n 'Dirty death flag is set',\n 'qmd collection missing',\n 'Uncommitted changes: 2'\n ])\n );\n expect(status.git?.dirtyCount).toBe(2);\n expect(status.qmd.indexStatus).toBe('missing');\n expect(status.links.total).toBe(0);\n expect(status.links.orphans).toBe(0);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('returns ok status when everything is healthy', async () => {\n hasQmdMock.mockReturnValue(true);\n execFileSyncMock.mockImplementation((command: string) => {\n if (command === 'qmd') {\n return JSON.stringify([{ name: mockCollection, root: mockRoot }]);\n }\n if (command === 'git') {\n return '';\n }\n return '';\n });\n\n const vaultPath = makeTempVaultDir();\n try {\n fs.mkdirSync(path.join(vaultPath, '.git'), { recursive: true });\n const clawvaultDir = path.join(vaultPath, '.clawvault');\n fs.mkdirSync(clawvaultDir, { recursive: true });\n const timestamp = new Date(Date.now() - 60_000).toISOString();\n fs.writeFileSync(\n path.join(clawvaultDir, 'last-checkpoint.json'),\n JSON.stringify({ timestamp, workingOn: 'sync', focus: null, blocked: null }, null, 2)\n );\n\n mockStats = { documents: 1, categories: { inbox: 1 } };\n mockCollection = 'vault';\n mockRoot = vaultPath;\n\n const status = await getStatus(vaultPath);\n expect(status.health).toBe('ok');\n expect(status.issues).toHaveLength(0);\n expect(status.checkpoint.exists).toBe(true);\n expect(status.qmd.indexStatus).toBe('present');\n expect(status.links.total).toBe(0);\n expect(status.links.orphans).toBe(0);\n const formatted = formatStatus(status);\n expect(formatted).toContain('Issues: none');\n expect(formatted).toContain('Links:');\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n});\n",452 "inputSchema": {},453 "outputSchema": null,454 "icons": null,455 "annotations": null,456 "meta": null,457 "execution": null458 },459 {460 "name": "sleep.ts",461 "title": null,462 "description": "Script: sleep.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as readline from 'readline';\nimport { execFileSync } from 'child_process';\nimport { ClawVault } from '../lib/vault.js';\nimport { qmdUpdate } from '../lib/search.js';\nimport type { Document, HandoffDocument } from '../types.js';\nimport { clearDirtyFlag } from './checkpoint.js';\n\nexport type PromptFn = (question: string) => Promise<string>;\n\nexport interface SleepOptions {\n workingOn: string;\n next?: string;\n blocked?: string;\n decisions?: string;\n questions?: string;\n feeling?: string;\n sessionKey?: string;\n vaultPath: string;\n index?: boolean;\n git?: boolean;\n prompt?: PromptFn;\n cwd?: string;\n}\n\nexport interface GitCommitResult {\n repoRoot?: string;\n dirtyCount?: number;\n committed: boolean;\n message?: string;\n skippedReason?: string;\n}\n\nexport interface SleepResult {\n handoff: HandoffDocument;\n document: Document;\n git?: GitCommitResult;\n}\n\nfunction isInteractive(): boolean {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\n\nasync function defaultPrompt(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nfunction parseList(raw?: string): string[] {\n if (!raw) return [];\n return raw\n .split(',')\n .map(item => item.trim())\n .filter(Boolean);\n}\n\nfunction ensureNonEmpty(label: string, items: string[]): void {\n if (items.length === 0) {\n throw new Error(`${label} is required.`);\n }\n}\n\nasync function promptForList(\n label: string,\n prompt: PromptFn,\n interactive: boolean\n): Promise<string[]> {\n if (!interactive) return [];\n const answer = await prompt(`${label} (comma-separated, empty to skip): `);\n return parseList(answer);\n}\n\nfunction findGitRoot(startPath: string): string | null {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, '.git'))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nfunction getGitStatus(repoRoot: string): { clean: boolean; dirtyCount: number } {\n const output = execFileSync('git', ['-C', repoRoot, 'status', '--porcelain'], {\n encoding: 'utf-8'\n });\n const lines = output.split('\\n').filter(Boolean);\n return { clean: lines.length === 0, dirtyCount: lines.length };\n}\n\nfunction isAffirmative(input: string): boolean {\n const normalized = input.trim().toLowerCase();\n return normalized === 'y' || normalized === 'yes';\n}\n\nasync function maybeCommitDirtyRepo(options: {\n enabled: boolean;\n prompt: PromptFn;\n cwd: string;\n interactive: boolean;\n}): Promise<GitCommitResult | undefined> {\n if (!options.enabled) {\n return { committed: false, skippedReason: 'disabled' };\n }\n\n const repoRoot = findGitRoot(options.cwd);\n if (!repoRoot) {\n return { committed: false, skippedReason: 'no-repo' };\n }\n\n let status: { clean: boolean; dirtyCount: number };\n try {\n status = getGitStatus(repoRoot);\n } catch (err: any) {\n if (err?.code === 'ENOENT') {\n return { committed: false, skippedReason: 'git-missing' };\n }\n return { repoRoot, committed: false, skippedReason: 'status-error' };\n }\n\n if (status.clean) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: 'clean' };\n }\n\n if (!options.interactive) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: 'non-interactive' };\n }\n\n const confirm = await options.prompt(\n `Git repo dirty (${status.dirtyCount} change(s)). Commit before sleep? (y/N): `\n );\n if (!isAffirmative(confirm)) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: 'declined' };\n }\n\n const message = await options.prompt('Commit message: ');\n if (!message) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: 'no-message' };\n }\n\n try {\n execFileSync('git', ['-C', repoRoot, 'add', '-A'], { stdio: 'inherit' });\n execFileSync('git', ['-C', repoRoot, 'commit', '-m', message], { stdio: 'inherit' });\n } catch (err: any) {\n throw new Error(`Git commit failed: ${err?.message || 'unknown error'}`);\n }\n\n return {\n repoRoot,\n dirtyCount: status.dirtyCount,\n committed: true,\n message\n };\n}\n\nexport async function sleep(options: SleepOptions): Promise<SleepResult> {\n const prompt = options.prompt ?? defaultPrompt;\n const interactive = isInteractive();\n const workingOn = parseList(options.workingOn);\n ensureNonEmpty('Working-on summary', workingOn);\n\n const nextProvided = options.next !== undefined;\n const blockedProvided = options.blocked !== undefined;\n\n let nextSteps = parseList(options.next);\n let blocked = parseList(options.blocked);\n\n if (!nextProvided) {\n nextSteps = await promptForList('Next steps', prompt, interactive);\n }\n\n if (!blockedProvided) {\n blocked = await promptForList('Blocked items', prompt, interactive);\n }\n\n const decisions = parseList(options.decisions);\n const questions = parseList(options.questions);\n\n const vault = new ClawVault(path.resolve(options.vaultPath));\n await vault.load();\n\n const handoffInput = {\n workingOn,\n blocked,\n nextSteps,\n decisions: decisions.length > 0 ? decisions : undefined,\n openQuestions: questions.length > 0 ? questions : undefined,\n feeling: options.feeling,\n sessionKey: options.sessionKey\n };\n\n const document = await vault.createHandoff(handoffInput);\n const handoff: HandoffDocument = {\n ...handoffInput,\n created: document.modified.toISOString()\n };\n await clearDirtyFlag(vault.getPath());\n\n if (options.index) {\n qmdUpdate(vault.getQmdCollection());\n }\n\n const git = await maybeCommitDirtyRepo({\n enabled: options.git !== false,\n prompt,\n cwd: options.cwd ?? process.cwd(),\n interactive\n });\n\n return { handoff, document, git };\n}\n",463 "inputSchema": {},464 "outputSchema": null,465 "icons": null,466 "annotations": null,467 "meta": null,468 "execution": null469 },470 {471 "name": "link.ts",472 "title": null,473 "description": "Script: link.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { buildEntityIndex, type EntityIndex } from '../lib/entity-index.js';\nimport { autoLink, dryRunLink, findUnlinkedMentions } from '../lib/auto-linker.js';\nimport { readBacklinksIndex, rebuildBacklinksIndex, scanVaultLinks } from '../lib/backlinks.js';\nimport { getVaultPath } from '../lib/config.js';\n\ninterface LinkOptions {\n all?: boolean;\n dryRun?: boolean;\n backlinks?: string;\n orphans?: boolean;\n rebuild?: boolean;\n}\n\nexport async function linkCommand(file: string | undefined, options: LinkOptions): Promise<void> {\n const vaultPath = getVaultPath();\n const index = buildEntityIndex(vaultPath);\n const suggestionIndex = filterIndex(index, new Set(['people', 'projects', 'decisions']));\n const modeCount = [options.backlinks ? 1 : 0, options.orphans ? 1 : 0, options.rebuild ? 1 : 0]\n .reduce((sum, value) => sum + value, 0);\n\n if (modeCount > 1) {\n console.error('Error: Use only one of --backlinks, --orphans, or --rebuild');\n process.exit(1);\n }\n\n if (options.rebuild) {\n const result = rebuildBacklinksIndex(vaultPath, { entityIndex: index });\n const orphanSuffix = result.orphans.length > 0 ? `, ${result.orphans.length} orphan(s)` : '';\n console.log(`\u2713 Rebuilt backlinks (${result.backlinks.size} targets, ${result.linkCount} links${orphanSuffix})`);\n return;\n }\n\n if (options.backlinks) {\n if (file) {\n console.error('Error: Use --backlinks without a file argument');\n process.exit(1);\n }\n const target = resolveBacklinkTarget(options.backlinks, vaultPath, index);\n if (!target) {\n console.error('Error: Invalid target for --backlinks');\n process.exit(1);\n }\n const backlinks = readBacklinksIndex(vaultPath)\n ?? rebuildBacklinksIndex(vaultPath, { entityIndex: index }).backlinks;\n const sources = backlinks.get(target) || [];\n if (sources.length === 0) {\n console.log(`No backlinks found for ${target}`);\n return;\n }\n console.log(`Backlinks \u2192 ${target}`);\n for (const source of sources.sort()) {\n console.log(` - ${source}`);\n }\n return;\n }\n\n if (options.orphans) {\n if (file || options.all) {\n console.error('Error: --orphans does not accept a file or --all');\n process.exit(1);\n }\n const result = scanVaultLinks(vaultPath, { entityIndex: index });\n if (result.orphans.length === 0) {\n console.log('\u2713 No orphan links found');\n return;\n }\n const orphans = result.orphans\n .slice()\n .sort((a, b) => a.target.localeCompare(b.target) || a.source.localeCompare(b.source));\n console.log(`\u26a0 ${orphans.length} orphan link(s) found`);\n for (const orphan of orphans) {\n console.log(` - ${orphan.source} \u2192 [[${orphan.target}]]`);\n }\n return;\n }\n \n if (options.all) {\n await linkAllFiles(vaultPath, index, suggestionIndex, options.dryRun);\n return;\n }\n \n if (!file) {\n console.error('Error: Specify a file or use --all');\n process.exit(1);\n }\n \n const filePath = path.isAbsolute(file) ? file : path.join(process.cwd(), file);\n \n if (!fs.existsSync(filePath)) {\n console.error(`Error: File not found: ${filePath}`);\n process.exit(1);\n }\n \n await linkFile(filePath, index, suggestionIndex, options.dryRun);\n}\n\nfunction filterIndex(index: EntityIndex, categories: Set<string>): EntityIndex {\n const entries = new Map<string, string>();\n const byPath = new Map<string, { path: string; aliases: string[] }>();\n\n for (const [alias, targetPath] of index.entries) {\n const category = targetPath.split('/')[0];\n if (categories.has(category)) {\n entries.set(alias, targetPath);\n }\n }\n\n for (const [targetPath, entry] of index.byPath) {\n const category = targetPath.split('/')[0];\n if (categories.has(category)) {\n byPath.set(targetPath, entry);\n }\n }\n\n return { entries, byPath };\n}\n\nfunction resolveBacklinkTarget(input: string, vaultPath: string, index: EntityIndex): string | null {\n let target = input.trim();\n if (!target) return null;\n if (target.startsWith('[[') && target.endsWith(']]')) {\n target = target.slice(2, -2);\n }\n const pipeIndex = target.indexOf('|');\n if (pipeIndex !== -1) {\n target = target.slice(0, pipeIndex);\n }\n const hashIndex = target.indexOf('#');\n if (hashIndex !== -1) {\n target = target.slice(0, hashIndex);\n }\n target = target.trim();\n if (!target) return null;\n if (target.endsWith('.md')) {\n target = target.slice(0, -3);\n }\n if (target.startsWith('/')) {\n target = target.slice(1);\n }\n\n const candidate = path.isAbsolute(target) ? target : path.join(vaultPath, target);\n const withExtension = candidate.endsWith('.md') ? candidate : `${candidate}.md`;\n if (fs.existsSync(candidate) && candidate.endsWith('.md')) {\n return toVaultId(vaultPath, candidate);\n }\n if (fs.existsSync(withExtension)) {\n return toVaultId(vaultPath, withExtension);\n }\n\n const aliasKey = target.toLowerCase();\n if (index.entries.has(aliasKey)) {\n return index.entries.get(aliasKey)!;\n }\n\n return target.replace(/\\\\/g, '/');\n}\n\nfunction toVaultId(vaultPath: string, filePath: string): string {\n const relative = path.relative(vaultPath, filePath).replace(/\\.md$/, '');\n return relative.split(path.sep).join('/');\n}\n\nfunction logSuggestions(filePath: string, suggestions: Array<{ alias: string; path: string; line: number }>): void {\n if (suggestions.length === 0) return;\n console.log(`\\n\ud83d\udca1 Suggested links in ${path.basename(filePath)}`);\n for (const suggestion of suggestions) {\n console.log(` Line ${suggestion.line}: \"${suggestion.alias}\" \u2192 [[${suggestion.path}]]`);\n }\n}\n\nasync function linkFile(\n filePath: string,\n index: ReturnType<typeof buildEntityIndex>,\n suggestionIndex: EntityIndex,\n dryRun?: boolean\n): Promise<number> {\n const content = fs.readFileSync(filePath, 'utf-8');\n const linkedContent = autoLink(content, index);\n const suggestions = findUnlinkedMentions(linkedContent, suggestionIndex);\n\n if (dryRun) {\n const matches = dryRunLink(content, index);\n if (matches.length > 0) {\n console.log(`\\n\ud83d\udcc4 ${filePath}`);\n for (const m of matches) {\n console.log(` Line ${m.line}: \"${m.alias}\" \u2192 [[${m.path}]]`);\n }\n }\n logSuggestions(filePath, suggestions);\n return matches.length;\n }\n\n if (linkedContent !== content) {\n fs.writeFileSync(filePath, linkedContent);\n const matches = dryRunLink(content, index);\n console.log(`\u2713 Linked ${matches.length} entities in ${path.basename(filePath)}`);\n logSuggestions(filePath, suggestions);\n return matches.length;\n }\n\n logSuggestions(filePath, suggestions);\n return 0;\n}\n\nasync function linkAllFiles(\n vaultPath: string,\n index: ReturnType<typeof buildEntityIndex>,\n suggestionIndex: EntityIndex,\n dryRun?: boolean\n): Promise<void> {\n const files: string[] = [];\n \n function walk(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n // Skip hidden folders and archive\n if (!entry.name.startsWith('.') && entry.name !== 'archive' && entry.name !== 'templates') {\n walk(fullPath);\n }\n } else if (entry.name.endsWith('.md')) {\n files.push(fullPath);\n }\n }\n }\n \n walk(vaultPath);\n \n let totalLinks = 0;\n let filesModified = 0;\n \n for (const file of files) {\n const links = await linkFile(file, index, suggestionIndex, dryRun);\n if (links > 0) {\n totalLinks += links;\n filesModified++;\n }\n }\n \n console.log(`\\n${dryRun ? '(dry run) ' : ''}${totalLinks} links in ${filesModified} files`);\n}\n",474 "inputSchema": {},475 "outputSchema": null,476 "icons": null,477 "annotations": null,478 "meta": null,479 "execution": null480 },481 {482 "name": "checkpoint.test.ts",483 "title": null,484 "description": "Script: checkpoint.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { execFileSyncMock } = vi.hoisted(() => ({\n execFileSyncMock: vi.fn()\n}));\n\nvi.mock('child_process', () => ({\n execFileSync: execFileSyncMock\n}));\n\nconst envSnapshot = {\n OPENCLAW_SESSION_KEY: process.env.OPENCLAW_SESSION_KEY,\n OPENCLAW_MODEL: process.env.OPENCLAW_MODEL,\n OPENCLAW_TOKEN_ESTIMATE: process.env.OPENCLAW_TOKEN_ESTIMATE,\n OPENCLAW_CONTEXT_TOKENS: process.env.OPENCLAW_CONTEXT_TOKENS\n};\n\nfunction makeTempVaultDir(): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-test-'));\n}\n\nasync function loadCheckpointModule() {\n vi.resetModules();\n return await import('./checkpoint.js');\n}\n\nafterEach(() => {\n vi.clearAllMocks();\n vi.useRealTimers();\n process.env.OPENCLAW_SESSION_KEY = envSnapshot.OPENCLAW_SESSION_KEY;\n process.env.OPENCLAW_MODEL = envSnapshot.OPENCLAW_MODEL;\n process.env.OPENCLAW_TOKEN_ESTIMATE = envSnapshot.OPENCLAW_TOKEN_ESTIMATE;\n process.env.OPENCLAW_CONTEXT_TOKENS = envSnapshot.OPENCLAW_CONTEXT_TOKENS;\n});\n\ndescribe('checkpoint debounce', () => {\n it('coalesces rapid checkpoint calls into a single disk write', async () => {\n vi.useFakeTimers();\n const { checkpoint } = await loadCheckpointModule();\n\n const vaultPath = makeTempVaultDir();\n try {\n const checkpointPath = path.join(vaultPath, '.clawvault', 'last-checkpoint.json');\n\n await checkpoint({ vaultPath, workingOn: 'a' });\n await vi.advanceTimersByTimeAsync(500);\n await checkpoint({ vaultPath, workingOn: 'b' });\n await vi.advanceTimersByTimeAsync(500);\n await checkpoint({ vaultPath, workingOn: 'c' });\n\n // Timer should have been reset by the last call.\n await vi.advanceTimersByTimeAsync(999);\n expect(fs.existsSync(checkpointPath)).toBe(false);\n\n await vi.advanceTimersByTimeAsync(1);\n expect(fs.existsSync(checkpointPath)).toBe(true);\n\n const saved = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));\n expect(saved.workingOn).toBe('c');\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('flush writes immediately and cancels the pending debounce', async () => {\n vi.useFakeTimers();\n const { checkpoint, flush } = await loadCheckpointModule();\n\n const vaultPath = makeTempVaultDir();\n try {\n const checkpointPath = path.join(vaultPath, '.clawvault', 'last-checkpoint.json');\n\n await checkpoint({ vaultPath, workingOn: 'soon' });\n const flushed = await flush();\n\n expect(flushed?.workingOn).toBe('soon');\n expect(fs.existsSync(checkpointPath)).toBe(true);\n const mtime = fs.statSync(checkpointPath).mtimeMs;\n\n await vi.advanceTimersByTimeAsync(2000);\n expect(fs.statSync(checkpointPath).mtimeMs).toBe(mtime);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('writes urgent checkpoints immediately and triggers a wake', async () => {\n execFileSyncMock.mockReturnValue('');\n const { checkpoint, checkDirtyDeath, clearDirtyFlag } = await loadCheckpointModule();\n\n const vaultPath = makeTempVaultDir();\n try {\n const checkpointPath = path.join(vaultPath, '.clawvault', 'last-checkpoint.json');\n const flagPath = path.join(vaultPath, '.clawvault', 'dirty-death.flag');\n\n const data = await checkpoint({ vaultPath, workingOn: 'urgent', urgent: true });\n\n expect(data.urgent).toBe(true);\n expect(fs.existsSync(checkpointPath)).toBe(true);\n expect(fs.existsSync(flagPath)).toBe(true);\n expect(execFileSyncMock).toHaveBeenCalledWith(\n 'openclaw',\n expect.arrayContaining(['gateway', 'wake', '--mode', 'now']),\n expect.objectContaining({ stdio: 'inherit' })\n );\n\n const deathInfo = await checkDirtyDeath(vaultPath);\n expect(deathInfo.died).toBe(true);\n expect(deathInfo.deathTime).toBeTruthy();\n\n await clearDirtyFlag(vaultPath);\n expect(fs.existsSync(flagPath)).toBe(false);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n\n it('uses env session details and persists startedAt', async () => {\n const { setSessionState, checkpoint } = await loadCheckpointModule();\n\n const vaultPath = makeTempVaultDir();\n try {\n await setSessionState(vaultPath, {\n sessionId: 'session-1',\n sessionKey: 'file-key',\n model: 'file-model',\n tokenEstimate: 123\n });\n\n const sessionPath = path.join(vaultPath, '.clawvault', 'session-state.json');\n const savedState = JSON.parse(fs.readFileSync(sessionPath, 'utf-8'));\n expect(savedState.startedAt).toBeTruthy();\n\n process.env.OPENCLAW_SESSION_KEY = 'env-key';\n process.env.OPENCLAW_MODEL = 'env-model';\n process.env.OPENCLAW_TOKEN_ESTIMATE = '456';\n\n const data = await checkpoint({ vaultPath, workingOn: 'work' });\n expect(data.sessionKey).toBe('env-key');\n expect(data.model).toBe('env-model');\n expect(data.tokenEstimate).toBe(456);\n expect(data.sessionStartedAt).toBe(savedState.startedAt);\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n }\n });\n});\n\n",485 "inputSchema": {},486 "outputSchema": null,487 "icons": null,488 "annotations": null,489 "meta": null,490 "execution": null491 },492 {493 "name": "template.ts",494 "title": null,495 "description": "Script: template.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport { buildTemplateVariables, renderTemplate, TemplateVariables } from '../lib/template-engine.js';\n\nconst VAULT_CONFIG_FILE = '.clawvault.json';\nconst TEMPLATE_EXTENSION = '.md';\n\nexport interface TemplateCommandContext {\n vaultPath?: string;\n cwd?: string;\n builtinDir?: string;\n}\n\nexport interface TemplateCreateOptions extends TemplateCommandContext {\n title?: string;\n type?: string;\n}\n\nexport interface TemplateAddOptions extends TemplateCommandContext {\n name: string;\n overwrite?: boolean;\n}\n\nfunction resolveBuiltinTemplatesDir(override?: string): string | null {\n if (override) {\n const resolved = path.resolve(override);\n return fs.existsSync(resolved) ? resolved : null;\n }\n\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(moduleDir, '../templates'),\n path.resolve(moduleDir, '../../templates')\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {\n return candidate;\n }\n }\n\n return null;\n}\n\nfunction findVaultRoot(start: string): string | null {\n let current = path.resolve(start);\n while (true) {\n if (fs.existsSync(path.join(current, VAULT_CONFIG_FILE))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nfunction resolveVaultPath(options: TemplateCommandContext): string | null {\n if (options.vaultPath) {\n return path.resolve(options.vaultPath);\n }\n\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n return path.resolve(envPath);\n }\n\n const cwd = options.cwd ?? process.cwd();\n return findVaultRoot(cwd);\n}\n\nfunction normalizeTemplateName(name: string): string {\n const base = path.basename(name, path.extname(name));\n return base.trim();\n}\n\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .trim();\n}\n\nfunction listTemplateFiles(dir: string, ignore?: Set<string>): Map<string, string> {\n const entries = new Map<string, string>();\n if (!fs.existsSync(dir)) return entries;\n\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(TEMPLATE_EXTENSION)) continue;\n const name = normalizeTemplateName(entry.name);\n if (!name) continue;\n if (ignore?.has(name)) continue;\n entries.set(name, path.join(dir, entry.name));\n }\n\n return entries;\n}\n\nfunction buildTemplateIndex(options: TemplateCommandContext): Map<string, string> {\n const index = new Map<string, string>();\n const builtinDir = resolveBuiltinTemplatesDir(options.builtinDir);\n if (builtinDir) {\n const ignore = new Set(['daily']);\n for (const [name, filePath] of listTemplateFiles(builtinDir, ignore)) {\n index.set(name, filePath);\n }\n }\n\n const vaultPath = resolveVaultPath(options);\n if (vaultPath) {\n const vaultTemplatesDir = path.join(vaultPath, 'templates');\n for (const [name, filePath] of listTemplateFiles(vaultTemplatesDir)) {\n index.set(name, filePath);\n }\n }\n\n return index;\n}\n\nexport function listTemplates(options: TemplateCommandContext = {}): string[] {\n const index = buildTemplateIndex(options);\n return [...index.keys()].sort();\n}\n\nexport function createFromTemplate(\n name: string,\n options: TemplateCreateOptions = {}\n): { outputPath: string; templatePath: string; variables: TemplateVariables } {\n const templateName = normalizeTemplateName(name);\n if (!templateName) {\n throw new Error('Template name is required.');\n }\n\n const index = buildTemplateIndex(options);\n const templatePath = index.get(templateName);\n if (!templatePath) {\n const available = [...index.keys()].sort();\n const hint = available.length > 0 ? ` Available: ${available.join(', ')}` : '';\n throw new Error(`Template not found: ${templateName}.${hint}`);\n }\n\n const raw = fs.readFileSync(templatePath, 'utf-8');\n const now = new Date();\n const date = now.toISOString().split('T')[0];\n const type = options.type ?? templateName;\n const title = options.title ?? `${type} ${date}`.trim();\n\n const variables = buildTemplateVariables({ title, type, date }, now);\n const rendered = renderTemplate(raw, variables);\n\n const cwd = options.cwd ?? process.cwd();\n const slug = slugify(title) || slugify(templateName) || `template-${date}`;\n const outputPath = path.join(cwd, `${slug}${TEMPLATE_EXTENSION}`);\n\n if (fs.existsSync(outputPath)) {\n throw new Error(`File already exists: ${outputPath}`);\n }\n\n fs.writeFileSync(outputPath, rendered);\n return { outputPath, templatePath, variables };\n}\n\nexport function addTemplate(\n file: string,\n options: TemplateAddOptions\n): { templatePath: string; name: string } {\n const name = normalizeTemplateName(options.name);\n if (!name) {\n throw new Error('Template name is required.');\n }\n\n const vaultPath = resolveVaultPath(options);\n if (!vaultPath) {\n throw new Error('No vault found. Set CLAWVAULT_PATH or use --vault.');\n }\n\n const cwd = options.cwd ?? process.cwd();\n const sourcePath = path.resolve(cwd, file);\n if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isFile()) {\n throw new Error(`Template file not found: ${sourcePath}`);\n }\n\n const templatesDir = path.join(vaultPath, 'templates');\n fs.mkdirSync(templatesDir, { recursive: true });\n\n const targetPath = path.join(templatesDir, `${name}${TEMPLATE_EXTENSION}`);\n if (fs.existsSync(targetPath) && !options.overwrite) {\n throw new Error(`Template already exists: ${targetPath}`);\n }\n\n fs.copyFileSync(sourcePath, targetPath);\n return { templatePath: targetPath, name };\n}\n",496 "inputSchema": {},497 "outputSchema": null,498 "icons": null,499 "annotations": null,500 "meta": null,501 "execution": null502 },503 {504 "name": "repair-session.ts",505 "title": null,506 "description": "Script: repair-session.ts. Code:\n/**\n * repair-session command - Repair corrupted OpenClaw session transcripts\n * \n * Fixes issues like:\n * - Aborted tool calls with partial JSON\n * - Orphaned tool_result messages referencing non-existent tool_use IDs\n * - Broken parent chain references\n */\n\nimport * as fs from 'fs';\nimport {\n listAgents,\n findMainSession,\n findSessionById,\n getSessionFilePath,\n type SessionInfo\n} from '../lib/session-utils.js';\n\nimport {\n analyzeSession,\n repairSession,\n type RepairResult\n} from '../lib/session-repair.js';\n\nexport interface RepairSessionOptions {\n sessionId?: string;\n agentId?: string;\n backup?: boolean;\n dryRun?: boolean;\n}\n\n/**\n * Resolve the session to repair\n */\nexport function resolveSession(options: RepairSessionOptions): SessionInfo | null {\n const { sessionId, agentId } = options;\n \n // If we have both session ID and agent ID, look up directly\n if (sessionId && agentId) {\n return findSessionById(agentId, sessionId);\n }\n \n // If we only have session ID, search all agents\n if (sessionId) {\n const agents = listAgents();\n for (const agent of agents) {\n const session = findSessionById(agent, sessionId);\n if (session) return session;\n }\n return null;\n }\n \n // If we only have agent ID, get main session\n if (agentId) {\n return findMainSession(agentId);\n }\n \n // Default: try to find a configured agent from environment\n const defaultAgent = process.env.OPENCLAW_AGENT_ID || 'clawdious';\n return findMainSession(defaultAgent);\n}\n\n/**\n * Format repair result for CLI output\n */\nexport function formatRepairResult(result: RepairResult, options: { dryRun?: boolean } = {}): string {\n const { dryRun = false } = options;\n const lines: string[] = [];\n \n lines.push(`Analyzing session: ${result.sessionId}`);\n lines.push('');\n \n if (result.corruptedEntries.length === 0) {\n lines.push('\u2705 No corruption detected. Session is clean.');\n return lines.join('\\n');\n }\n \n if (dryRun) {\n lines.push(`Found ${result.corruptedEntries.length} corrupted entries:`);\n } else {\n lines.push(`Found and fixed ${result.corruptedEntries.length} corrupted entries:`);\n }\n \n for (const entry of result.corruptedEntries) {\n const prefix = entry.type === 'aborted_tool_use' ? 'Aborted tool_use' : 'Orphaned tool_result';\n lines.push(` - Line ${entry.lineNumber}: ${prefix} (id: ${entry.toolUseId})`);\n }\n \n if (result.parentRelinks.length > 0) {\n lines.push('');\n if (dryRun) {\n lines.push(`Would relink ${result.parentRelinks.length} parent reference(s):`);\n } else {\n lines.push(`Relinked ${result.parentRelinks.length} parent reference(s):`);\n }\n for (const relink of result.parentRelinks.slice(0, 5)) {\n lines.push(` - Line ${relink.lineNumber}: parentId ${relink.oldParentId.slice(0, 8)}\u2026 \u2192 ${relink.newParentId === 'null' ? 'null' : relink.newParentId.slice(0, 8)}\u2026`);\n }\n if (result.parentRelinks.length > 5) {\n lines.push(` ... and ${result.parentRelinks.length - 5} more`);\n }\n }\n \n lines.push('');\n \n if (dryRun) {\n lines.push(`Would remove ${result.removedCount} entries, relink ${result.relinkedCount} parent references.`);\n } else {\n lines.push(`\u2705 Session repaired: removed ${result.removedCount} entries, relinked ${result.relinkedCount} parent references`);\n if (result.backupPath) {\n const backupName = result.backupPath.split('/').pop();\n lines.push(`Backup saved: ${backupName}`);\n }\n }\n \n return lines.join('\\n');\n}\n\n/**\n * Main repair-session command handler\n */\nexport async function repairSessionCommand(options: RepairSessionOptions): Promise<RepairResult> {\n const { backup = true, dryRun = false } = options;\n \n const session = resolveSession(options);\n \n if (!session) {\n throw new Error(\n options.sessionId\n ? `Session not found: ${options.sessionId}`\n : options.agentId\n ? `No main session found for agent: ${options.agentId}`\n : 'No session found. Specify --session or --agent.'\n );\n }\n \n if (!fs.existsSync(session.filePath)) {\n throw new Error(`Session file not found: ${session.filePath}`);\n }\n \n if (dryRun) {\n return analyzeSession(session.filePath);\n }\n \n return repairSession(session.filePath, { backup, dryRun: false });\n}\n\n/**\n * List available sessions for an agent (for --list flag)\n */\nexport function listAgentSessions(agentId?: string): string {\n const agents = agentId ? [agentId] : listAgents();\n const lines: string[] = [];\n \n if (agents.length === 0) {\n return 'No agents found in ~/.openclaw/agents/';\n }\n \n for (const agent of agents) {\n const mainSession = findMainSession(agent);\n if (mainSession) {\n lines.push(`${agent}:`);\n lines.push(` Main session: ${mainSession.sessionId}`);\n lines.push(` File: ${mainSession.filePath}`);\n if (mainSession.updatedAt) {\n const date = new Date(mainSession.updatedAt);\n lines.push(` Updated: ${date.toISOString()}`);\n }\n lines.push('');\n }\n }\n \n if (lines.length === 0) {\n return agentId\n ? `No sessions found for agent: ${agentId}`\n : 'No sessions found.';\n }\n \n return lines.join('\\n');\n}\n",507 "inputSchema": {},508 "outputSchema": null,509 "icons": null,510 "annotations": null,511 "meta": null,512 "execution": null513 },514 {515 "name": "doctor.test.ts",516 "title": null,517 "description": "Script: doctor.test.ts. Code:\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nconst { hasQmdMock, scanVaultLinksMock } = vi.hoisted(() => ({\n hasQmdMock: vi.fn(),\n scanVaultLinksMock: vi.fn()\n}));\n\nlet mockStats = { documents: 0, categories: {} as Record<string, number> };\nlet mockDocuments: Array<{\n id: string;\n path: string;\n category: string;\n title: string;\n content: string;\n frontmatter: Record<string, unknown>;\n links: string[];\n tags: string[];\n modified: Date;\n}> = [];\nlet mockHandoffs: typeof mockDocuments = [];\nlet mockInbox: typeof mockDocuments = [];\n\nvi.mock('../lib/search.js', async () => {\n const actual = await vi.importActual<typeof import('../lib/search.js')>('../lib/search.js');\n return {\n ...actual,\n hasQmd: hasQmdMock\n };\n});\n\nvi.mock('../lib/backlinks.js', () => ({\n scanVaultLinks: scanVaultLinksMock\n}));\n\nvi.mock('../lib/vault.js', () => ({\n ClawVault: class {\n private vaultPath: string;\n\n constructor(vaultPath: string) {\n this.vaultPath = vaultPath;\n }\n\n async load(): Promise<void> {\n return;\n }\n\n async stats(): Promise<{ documents: number; categories: Record<string, number> }> {\n return mockStats;\n }\n\n async list(category?: string) {\n if (category === 'handoffs') return mockHandoffs;\n if (category === 'inbox') return mockInbox;\n if (category) return [];\n return mockDocuments;\n }\n\n getPath(): string {\n return this.vaultPath;\n }\n\n getQmdCollection(): string {\n return 'vault';\n }\n },\n findVault: async () => null\n}));\n\nimport { doctor } from './doctor.js';\n\nfunction makeDoc(category: string, modified: Date) {\n return {\n id: `${category}/doc`,\n path: `/tmp/${category}/doc.md`,\n category,\n title: 'doc',\n content: '',\n frontmatter: {},\n links: [],\n tags: [],\n modified\n };\n}\n\nfunction makeTempDir(prefix: string): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), prefix));\n}\n\nconst envSnapshot = {\n HOME: process.env.HOME,\n SHELL: process.env.SHELL\n};\n\nafterEach(() => {\n vi.clearAllMocks();\n process.env.HOME = envSnapshot.HOME;\n process.env.SHELL = envSnapshot.SHELL;\n});\n\ndescribe('doctor', () => {\n it('reports when qmd is unavailable', async () => {\n hasQmdMock.mockReturnValue(false);\n const report = await doctor('/tmp/vault');\n const qmdCheck = report.checks.find(check => check.label === 'qmd installed');\n expect(qmdCheck?.status).toBe('error');\n expect(report.errors).toBeGreaterThan(0);\n });\n\n it('warns on stale handoff/checkpoint and backlog', async () => {\n hasQmdMock.mockReturnValue(true);\n scanVaultLinksMock.mockReturnValue({\n backlinks: new Map(),\n orphans: Array.from({ length: 25 }, () => ({ source: 'a', target: 'b' })),\n linkCount: 30\n });\n\n const vaultPath = makeTempDir('clawvault-doctor-');\n const homePath = makeTempDir('clawvault-home-');\n const clawvaultDir = path.join(vaultPath, '.clawvault');\n fs.mkdirSync(clawvaultDir, { recursive: true });\n const checkpointTime = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString();\n fs.writeFileSync(\n path.join(clawvaultDir, 'last-checkpoint.json'),\n JSON.stringify({ timestamp: checkpointTime }, null, 2)\n );\n\n process.env.HOME = homePath;\n process.env.SHELL = '/bin/bash';\n fs.writeFileSync(path.join(homePath, '.bashrc'), 'export CLAWVAULT_PATH=\"/tmp/vault\"');\n\n mockStats = { documents: 10, categories: { inbox: 6 } };\n mockDocuments = [makeDoc('projects', new Date())];\n mockHandoffs = [makeDoc('handoffs', new Date(Date.now() - 3 * 24 * 60 * 60 * 1000))];\n mockInbox = Array.from({ length: 6 }, () => makeDoc('inbox', new Date()));\n\n try {\n const report = await doctor(vaultPath);\n const warnings = report.checks.filter(check => check.status === 'warn').map(check => check.label);\n expect(warnings).toEqual(expect.arrayContaining([\n 'recent handoff',\n 'checkpoint freshness',\n 'orphan links',\n 'inbox backlog'\n ]));\n } finally {\n fs.rmSync(vaultPath, { recursive: true, force: true });\n fs.rmSync(homePath, { recursive: true, force: true });\n }\n });\n});\n",518 "inputSchema": {},519 "outputSchema": null,520 "icons": null,521 "annotations": null,522 "meta": null,523 "execution": null524 },525 {526 "name": "wake.ts",527 "title": null,528 "description": "Script: wake.ts. Code:\nimport * as path from 'path';\nimport { ClawVault } from '../lib/vault.js';\nimport type { SessionRecap } from '../types.js';\nimport { clearDirtyFlag } from './checkpoint.js';\nimport { recover, type RecoveryInfo } from './recover.js';\n\nexport interface WakeOptions {\n vaultPath: string;\n handoffLimit?: number;\n brief?: boolean;\n}\n\nexport interface WakeResult {\n recovery: RecoveryInfo;\n recap: SessionRecap;\n recapMarkdown: string;\n summary: string;\n}\n\nconst DEFAULT_HANDOFF_LIMIT = 3;\n\nfunction formatSummaryItems(items: string[], maxItems: number = 2): string {\n const cleaned = items.map(item => item.trim()).filter(Boolean);\n if (cleaned.length === 0) return '';\n if (cleaned.length <= maxItems) return cleaned.join(', ');\n return `${cleaned.slice(0, maxItems).join(', ')} +${cleaned.length - maxItems} more`;\n}\n\nexport function buildWakeSummary(recovery: RecoveryInfo, recap: SessionRecap): string {\n if (recovery.checkpoint?.workingOn) {\n return recovery.checkpoint.workingOn;\n }\n\n const latestHandoff = recap.recentHandoffs[0];\n if (latestHandoff?.workingOn?.length) {\n return formatSummaryItems(latestHandoff.workingOn);\n }\n\n if (recap.activeProjects.length > 0) {\n return formatSummaryItems(recap.activeProjects);\n }\n\n return 'No recent work summary found.';\n}\n\nexport async function wake(options: WakeOptions): Promise<WakeResult> {\n const vaultPath = path.resolve(options.vaultPath);\n const recovery = await recover(vaultPath, { clearFlag: true });\n await clearDirtyFlag(vaultPath);\n\n const vault = new ClawVault(vaultPath);\n await vault.load();\n const recap = await vault.generateRecap({\n handoffLimit: options.handoffLimit ?? DEFAULT_HANDOFF_LIMIT,\n brief: options.brief ?? true\n });\n const summary = buildWakeSummary(recovery, recap);\n const recapMarkdown = vault.formatRecap(recap, { brief: options.brief ?? true });\n\n return {\n recovery,\n recap,\n recapMarkdown,\n summary\n };\n}\n",529 "inputSchema": {},530 "outputSchema": null,531 "icons": null,532 "annotations": null,533 "meta": null,534 "execution": null535 },536 {537 "name": "setup.ts",538 "title": null,539 "description": "Script: setup.ts. Code:\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { execFileSync } from 'child_process';\nimport { DEFAULT_CATEGORIES } from '../types.js';\nimport { hasQmd } from '../lib/search.js';\nconst CONFIG_FILE = '.clawvault.json';\nfunction resolveVaultTarget(): { vaultPath: string; source: string; existed: boolean } {\n const envPath = process.env.CLAWVAULT_PATH?.trim();\n const home = os.homedir();\n \n // If CLAWVAULT_PATH is set, always use it (create if needed)\n if (envPath) {\n const vaultPath = path.resolve(envPath);\n return { vaultPath, source: 'CLAWVAULT_PATH', existed: fs.existsSync(vaultPath) };\n }\n \n // Otherwise check for existing vaults in priority order\n const candidates = [\n { vaultPath: path.join(home, '.openclaw', 'workspace', 'memory'), source: 'OpenClaw default' },\n { vaultPath: path.resolve(process.cwd(), 'memory'), source: './memory' },\n { vaultPath: path.join(home, 'memory'), source: '~/memory' }\n ];\n \n for (const candidate of candidates) {\n if (fs.existsSync(candidate.vaultPath)) {\n return { ...candidate, existed: true };\n }\n }\n \n // Default to OpenClaw path for new vaults\n const fallback = candidates[0];\n return { ...fallback, existed: false };\n}\nfunction ensureVaultStructure(vaultPath: string): boolean {\n fs.mkdirSync(vaultPath, { recursive: true });\n for (const category of DEFAULT_CATEGORIES) {\n fs.mkdirSync(path.join(vaultPath, category), { recursive: true });\n }\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (fs.existsSync(configPath)) return false;\n const now = new Date().toISOString();\n const name = path.basename(vaultPath);\n const meta = {\n name,\n version: '1.0.0',\n created: now,\n lastUpdated: now,\n categories: DEFAULT_CATEGORIES,\n documentCount: 0,\n qmdCollection: name,\n qmdRoot: vaultPath\n };\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n return true;\n}\nfunction getQmdConfig(vaultPath: string): { collection: string; root: string } {\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n try {\n const meta = JSON.parse(fs.readFileSync(configPath, 'utf-8')) as {\n name?: string;\n qmdCollection?: string;\n qmdRoot?: string;\n };\n return {\n collection: meta.qmdCollection || meta.name || path.basename(vaultPath),\n root: meta.qmdRoot || vaultPath\n };\n } catch {\n return { collection: path.basename(vaultPath), root: vaultPath };\n }\n }\n return { collection: path.basename(vaultPath), root: vaultPath };\n}\nexport async function setupCommand(): Promise<void> {\n const target = resolveVaultTarget();\n if (target.existed && !fs.statSync(target.vaultPath).isDirectory()) {\n throw new Error(`Vault path is not a directory: ${target.vaultPath}`);\n }\n if (!target.existed) fs.mkdirSync(target.vaultPath, { recursive: true });\n console.log(`${target.existed ? 'Found' : 'Created'} vault path (${target.source}): ${target.vaultPath}`);\n const initialized = ensureVaultStructure(target.vaultPath);\n console.log(initialized ? 'Initialized vault structure.' : 'Vault structure already present.');\n console.log('\\nTip: add this to your shell config:');\n console.log(` export CLAWVAULT_PATH=\"${target.vaultPath}\"`);\n if (hasQmd()) {\n const { collection, root } = getQmdConfig(target.vaultPath);\n try {\n execFileSync('qmd', ['collection', 'add', root, '--name', collection, '--mask', '**/*.md'], {\n stdio: 'ignore'\n });\n console.log(`qmd collection ready: ${collection}`);\n } catch {\n console.log('qmd collection already exists or could not be created.');\n }\n } else {\n console.log('qmd not found; skipping collection setup.');\n }\n}\n",540 "inputSchema": {},541 "outputSchema": null,542 "icons": null,543 "annotations": null,544 "meta": null,545 "execution": null546 },547 {548 "name": "shell-init.test.ts",549 "title": null,550 "description": "Script: shell-init.test.ts. Code:\nimport { describe, expect, it } from 'vitest';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { shellInit } from './shell-init.js';\n\nfunction makeTempDir(prefix: string): string {\n return fs.mkdtempSync(path.join(os.tmpdir(), prefix));\n}\n\ndescribe('shellInit', () => {\n it('uses CLAWVAULT_PATH from env when provided', () => {\n const output = shellInit({\n env: { CLAWVAULT_PATH: '/tmp/vault' } as NodeJS.ProcessEnv,\n cwd: '/'\n });\n expect(output).toContain(\"export CLAWVAULT_PATH='/tmp/vault'\");\n expect(output).toContain(\"alias cvwake='clawvault wake'\");\n expect(output).toContain(\"alias cvsleep='clawvault sleep'\");\n expect(output).toContain(\"alias cvcheck='clawvault doctor'\");\n });\n\n it('detects a vault path from cwd when env is empty', () => {\n const dir = makeTempDir('clawvault-shell-');\n try {\n fs.writeFileSync(path.join(dir, '.clawvault.json'), '{}');\n const output = shellInit({\n env: {} as NodeJS.ProcessEnv,\n cwd: dir\n });\n expect(output).toContain(`export CLAWVAULT_PATH='${dir}'`);\n } finally {\n fs.rmSync(dir, { recursive: true, force: true });\n }\n });\n});\n",551 "inputSchema": {},552 "outputSchema": null,553 "icons": null,554 "annotations": null,555 "meta": null,556 "execution": null557 },558 {559 "name": "entities.ts",560 "title": null,561 "description": "Script: entities.ts. Code:\nimport { buildEntityIndex } from '../lib/entity-index.js';\nimport { getVaultPath } from '../lib/config.js';\n\ninterface EntitiesOptions {\n json?: boolean;\n}\n\nexport async function entitiesCommand(options: EntitiesOptions): Promise<void> {\n const vaultPath = getVaultPath();\n const index = buildEntityIndex(vaultPath);\n \n if (options.json) {\n const output: Record<string, string[]> = {};\n for (const [path, entry] of index.byPath) {\n output[path] = entry.aliases;\n }\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n \n // Group by folder\n const byFolder: Record<string, Array<{ path: string; aliases: string[] }>> = {};\n \n for (const [path, entry] of index.byPath) {\n const folder = path.split('/')[0];\n if (!byFolder[folder]) byFolder[folder] = [];\n byFolder[folder].push({ path, aliases: entry.aliases });\n }\n \n console.log('\ud83d\udcda Linkable Entities\\n');\n \n for (const [folder, entities] of Object.entries(byFolder)) {\n console.log(`## ${folder}/`);\n for (const entity of entities) {\n const name = entity.path.split('/')[1];\n const otherAliases = entity.aliases.filter(a => a.toLowerCase() !== name.toLowerCase());\n if (otherAliases.length > 0) {\n console.log(` - ${name} (${otherAliases.join(', ')})`);\n } else {\n console.log(` - ${name}`);\n }\n }\n console.log();\n }\n \n console.log(`Total: ${index.byPath.size} entities, ${index.entries.size} linkable aliases`);\n}\n",562 "inputSchema": {},563 "outputSchema": null,564 "icons": null,565 "annotations": null,566 "meta": null,567 "execution": null568 },569 {570 "name": "shell-init.ts",571 "title": null,572 "description": "Script: shell-init.ts. Code:\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nfunction detectVaultPath(startPath: string): string | null {\n let current = path.resolve(startPath);\n while (true) {\n const configPath = path.join(current, '.clawvault.json');\n if (fs.existsSync(configPath)) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nexport interface ShellInitOptions {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n}\n\nexport function shellInit(options: ShellInitOptions = {}): string {\n const env = options.env ?? process.env;\n const cwd = options.cwd ?? process.cwd();\n const detected = env.CLAWVAULT_PATH || detectVaultPath(cwd);\n\n const lines: string[] = [];\n lines.push('# ClawVault shell integration');\n\n if (detected) {\n lines.push('if [ -z \"$CLAWVAULT_PATH\" ]; then');\n lines.push(` export CLAWVAULT_PATH=${shellQuote(path.resolve(detected))}`);\n lines.push('fi');\n } else {\n lines.push('# Set CLAWVAULT_PATH to your vault directory:');\n lines.push('# export CLAWVAULT_PATH=\"/path/to/vault\"');\n }\n\n lines.push(\"alias cvwake='clawvault wake'\");\n lines.push(\"alias cvsleep='clawvault sleep'\");\n lines.push(\"alias cvcheck='clawvault doctor'\");\n\n return lines.join('\\n');\n}\n",573 "inputSchema": {},574 "outputSchema": null,575 "icons": null,576 "annotations": null,577 "meta": null,578 "execution": null579 },580 {581 "name": "types.ts",582 "title": null,583 "description": "Script: types.ts. Code:\n/**\n * ClawVault Types - The elephant's memory structure\n */\n\nexport interface VaultConfig {\n /** Root path of the vault */\n path: string;\n /** Name of the vault */\n name: string;\n /** Categories to create on init */\n categories: string[];\n /** qmd collection name (defaults to vault name if not set) */\n qmdCollection?: string;\n /** Root path for qmd collection (defaults to vault path) */\n qmdRoot?: string;\n /** Custom templates path (optional) */\n templatesPath?: string;\n}\n\nexport interface VaultMeta {\n name: string;\n version: string;\n created: string;\n lastUpdated: string;\n categories: string[];\n documentCount: number;\n /** qmd collection name (defaults to vault name if not set) */\n qmdCollection?: string;\n /** Root path for qmd collection (defaults to vault path) */\n qmdRoot?: string;\n}\n\nexport interface Document {\n /** Unique ID (relative path without extension) */\n id: string;\n /** Full file path */\n path: string;\n /** Category (folder name) */\n category: string;\n /** Document title */\n title: string;\n /** Raw content */\n content: string;\n /** Frontmatter metadata */\n frontmatter: Record<string, unknown>;\n /** Extracted wiki-links [[like-this]] */\n links: string[];\n /** Tags extracted from content */\n tags: string[];\n /** Last modified timestamp */\n modified: Date;\n}\n\nexport interface SearchResult {\n /** Document that matched */\n document: Document;\n /** Relevance score (0-1) */\n score: number;\n /** Matching snippet */\n snippet: string;\n /** Which terms matched */\n matchedTerms: string[];\n}\n\nexport interface SearchOptions {\n /** Max results to return */\n limit?: number;\n /** Minimum score threshold (0-1) */\n minScore?: number;\n /** Filter by category */\n category?: string;\n /** Filter by tags */\n tags?: string[];\n /** Include full content in results */\n fullContent?: boolean;\n}\n\nexport interface StoreOptions {\n /** Category to store in */\n category: string;\n /** Document title (used for filename) */\n title: string;\n /** Content body */\n content: string;\n /** Frontmatter metadata */\n frontmatter?: Record<string, unknown>;\n /** Override existing file */\n overwrite?: boolean;\n /** Trigger qmd update after storing */\n qmdUpdate?: boolean;\n /** Trigger qmd embed after storing (implies qmdUpdate) */\n qmdEmbed?: boolean;\n}\n\nexport interface SyncOptions {\n /** Target directory to sync to */\n target: string;\n /** Delete files in target not in source */\n deleteOrphans?: boolean;\n /** Dry run - don't actually sync */\n dryRun?: boolean;\n}\n\nexport interface SyncResult {\n copied: string[];\n deleted: string[];\n unchanged: string[];\n errors: string[];\n}\n\nexport type Category = \n | 'preferences'\n | 'decisions'\n | 'patterns'\n | 'people'\n | 'projects'\n | 'goals'\n | 'transcripts'\n | 'inbox'\n | 'templates'\n | 'facts'\n | 'feelings'\n | 'lessons'\n | 'commitments'\n | 'handoffs'\n | string;\n\nexport const DEFAULT_CATEGORIES: Category[] = [\n 'preferences',\n 'decisions',\n 'patterns',\n 'people',\n 'projects',\n 'goals',\n 'transcripts',\n 'inbox',\n 'templates'\n];\n\n/**\n * Memory Type Taxonomy (Benthic's 8 categories)\n * Knowing WHAT KIND of thing helps you know WHERE to put it\n */\nexport type MemoryType = \n | 'fact' // Raw information, data points\n | 'feeling' // Emotional states, reactions, moods\n | 'decision' // Choices made with reasoning\n | 'lesson' // What I learned, insights, patterns\n | 'commitment' // Promises, goals, obligations\n | 'preference' // Likes, dislikes, how I want things\n | 'relationship'// People, connections, dynamics\n | 'project'; // Active work, ventures, ongoing efforts\n\nexport const MEMORY_TYPES: MemoryType[] = [\n 'fact', 'feeling', 'decision', 'lesson', \n 'commitment', 'preference', 'relationship', 'project'\n];\n\n/**\n * Memory type to category mapping\n */\nexport const TYPE_TO_CATEGORY: Record<MemoryType, Category> = {\n fact: 'facts',\n feeling: 'feelings',\n decision: 'decisions',\n lesson: 'lessons',\n commitment: 'commitments',\n preference: 'preferences',\n relationship: 'people',\n project: 'projects'\n};\n\n/**\n * Handoff document - bridges sessions\n */\nexport interface HandoffDocument {\n /** When this handoff was created */\n created: string;\n /** Session key or identifier */\n sessionKey?: string;\n /** What I was working on */\n workingOn: string[];\n /** What is currently blocked */\n blocked: string[];\n /** What comes next */\n nextSteps: string[];\n /** Emotional state/energy */\n feeling?: string;\n /** Key decisions made */\n decisions?: string[];\n /** Open questions */\n openQuestions?: string[];\n}\n\n/**\n * Session recap - who I was when I woke up\n */\nexport interface SessionRecap {\n /** When recap was generated */\n generated: string;\n /** Recent handoffs (last N) */\n recentHandoffs: HandoffDocument[];\n /** Active projects */\n activeProjects: string[];\n /** Pending commitments */\n pendingCommitments: string[];\n /** Recent decisions made */\n recentDecisions?: string[];\n /** Recent lessons learned */\n recentLessons: string[];\n /** Key relationships to remember */\n keyRelationships: string[];\n /** Current emotional arc */\n emotionalArc?: string;\n}\n\nexport const DEFAULT_CONFIG: Partial<VaultConfig> = {\n categories: DEFAULT_CATEGORIES\n};\n",584 "inputSchema": {},585 "outputSchema": null,586 "icons": null,587 "annotations": null,588 "meta": null,589 "execution": null590 },591 {592 "name": "index.ts",593 "title": null,594 "description": "Script: index.ts. Code:\n/**\n * ClawVault \ud83d\udc18 \u2014 An Elephant Never Forgets\n * \n * Structured memory system for AI agents with Obsidian-compatible markdown\n * and embedded semantic search.\n * \n * @example\n * ```typescript\n * import { ClawVault, createVault, findVault } from 'clawvault';\n * \n * // Create a new vault\n * const vault = await createVault('./my-memory');\n * \n * // Store a memory\n * await vault.store({\n * category: 'decisions',\n * title: 'Use ClawVault',\n * content: 'Decided to use ClawVault for memory management.'\n * });\n * \n * // Search memories\n * const results = await vault.find('memory management');\n * console.log(results);\n * ```\n */\n\nimport * as fs from 'fs';\n\n// Core exports\nexport { ClawVault, createVault, findVault } from './lib/vault.js';\nexport { setupCommand } from './commands/setup.js';\nexport {\n SearchEngine,\n extractWikiLinks,\n extractTags,\n hasQmd,\n qmdUpdate,\n qmdEmbed,\n QmdUnavailableError,\n QMD_INSTALL_COMMAND,\n QMD_INSTALL_URL\n} from './lib/search.js';\n\nexport {\n renderTemplate,\n buildTemplateVariables\n} from './lib/template-engine.js';\nexport type { TemplateVariables } from './lib/template-engine.js';\n\n// Type exports\nexport type {\n VaultConfig,\n VaultMeta,\n Document,\n SearchResult,\n SearchOptions,\n StoreOptions,\n SyncOptions,\n SyncResult,\n Category,\n MemoryType,\n HandoffDocument,\n SessionRecap\n} from './types.js';\n\nexport { DEFAULT_CATEGORIES, DEFAULT_CONFIG, MEMORY_TYPES, TYPE_TO_CATEGORY } from './types.js';\n\n// Version\nfunction readPackageVersion(): string {\n try {\n const pkgUrl = new URL('../package.json', import.meta.url);\n const pkg = JSON.parse(fs.readFileSync(pkgUrl, 'utf-8')) as { version?: string };\n return pkg.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nexport const VERSION = readPackageVersion();\n",595 "inputSchema": {},596 "outputSchema": null,597 "icons": null,598 "annotations": null,599 "meta": null,600 "execution": null601 },602 {603 "name": "clawvault.js",604 "title": null,605 "description": "Script: clawvault.js. Code:\n#!/usr/bin/env node\n\n/**\n * ClawVault CLI \ud83d\udc18\n * An elephant never forgets.\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { spawn } from 'child_process';\nimport {\n ClawVault,\n createVault,\n findVault,\n QmdUnavailableError,\n QMD_INSTALL_COMMAND\n} from '../dist/index.js';\n\nconst program = new Command();\n\nconst CLI_VERSION = (() => {\n try {\n const pkgUrl = new URL('../package.json', import.meta.url);\n const pkg = JSON.parse(fs.readFileSync(pkgUrl, 'utf-8'));\n return pkg.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n})();\n\n// Helper to get vault (required for most commands)\n// Checks: 1) explicit path, 2) CLAWVAULT_PATH env, 3) walk up from cwd\nasync function getVault(vaultPath) {\n // Explicit path takes priority\n if (vaultPath) {\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n return vault;\n }\n \n // Check environment variable\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n const vault = new ClawVault(path.resolve(envPath));\n await vault.load();\n return vault;\n }\n \n // Walk up from cwd\n const vault = await findVault();\n if (!vault) {\n console.error(chalk.red('Error: No ClawVault found. Run `clawvault init` first.'));\n console.log(chalk.dim('Tip: Set CLAWVAULT_PATH environment variable to your vault path'));\n process.exit(1);\n }\n return vault;\n}\n\nfunction resolveVaultPath(vaultPath) {\n if (vaultPath) {\n return path.resolve(vaultPath);\n }\n if (process.env.CLAWVAULT_PATH) {\n return path.resolve(process.env.CLAWVAULT_PATH);\n }\n let current = process.cwd();\n while (true) {\n if (fs.existsSync(path.join(current, '.clawvault.json'))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n console.error(chalk.red('Error: No ClawVault found. Run `clawvault init` first.'));\n console.log(chalk.dim('Tip: Set CLAWVAULT_PATH environment variable to your vault path'));\n process.exit(1);\n }\n current = parent;\n }\n}\n\nasync function runQmd(args) {\n return new Promise((resolve, reject) => {\n const proc = spawn('qmd', args, { stdio: 'inherit' });\n proc.on('close', (code) => {\n if (code === 0) resolve();\n else reject(new Error(`qmd exited with code ${code}`));\n });\n proc.on('error', (err) => {\n if (err?.code === 'ENOENT') {\n reject(new QmdUnavailableError());\n } else {\n reject(err);\n }\n });\n });\n}\n\nfunction printQmdMissing() {\n console.error(chalk.red('Error: ClawVault requires qmd.'));\n console.log(chalk.dim(`Install: ${QMD_INSTALL_COMMAND}`));\n}\n\nprogram\n .name('clawvault')\n .description('\ud83d\udc18 An elephant never forgets. Structured memory for AI agents.')\n .version(CLI_VERSION);\n\n// === INIT ===\nprogram\n .command('init [path]')\n .description('Initialize a new ClawVault')\n .option('-n, --name <name>', 'Vault name')\n .option('--qmd', 'Set up qmd semantic search collection')\n .option('--qmd-collection <name>', 'qmd collection name (defaults to vault name)')\n .action(async (vaultPath, options) => {\n const targetPath = vaultPath || '.';\n console.log(chalk.cyan(`\\n\ud83d\udc18 Initializing ClawVault at ${path.resolve(targetPath)}...\\n`));\n \n try {\n const vault = await createVault(targetPath, {\n name: options.name || path.basename(path.resolve(targetPath)),\n qmdCollection: options.qmdCollection\n });\n \n console.log(chalk.green('\u2713 Vault created'));\n console.log(chalk.dim(` Categories: ${vault.getCategories().join(', ')}`));\n\n // Always set up qmd collection (qmd is required)\n console.log(chalk.cyan('\\nSetting up qmd collection...'));\n try {\n await runQmd([\n 'collection',\n 'add',\n vault.getQmdRoot(),\n '--name',\n vault.getQmdCollection(),\n '--mask',\n '**/*.md'\n ]);\n console.log(chalk.green('\u2713 qmd collection created'));\n } catch (err) {\n // Collection might already exist\n console.log(chalk.yellow('\u26a0 qmd collection may already exist'));\n }\n \n console.log(chalk.green('\\n\u2705 ClawVault ready!\\n'));\n console.log(chalk.dim('Next steps:'));\n console.log(chalk.dim(' clawvault store --category inbox --title \"My note\" --content \"Hello world\"'));\n console.log(chalk.dim(' clawvault search \"hello\"'));\n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SETUP ===\nprogram\n .command('setup')\n .description('Auto-discover and configure a ClawVault')\n .action(async () => {\n try {\n const { setupCommand } = await import('../dist/commands/setup.js');\n await setupCommand();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === STORE ===\nprogram\n .command('store')\n .description('Store a new memory')\n .requiredOption('-c, --category <category>', 'Category (preferences, decisions, patterns, people, projects, goals, transcripts, inbox)')\n .requiredOption('-t, --title <title>', 'Document title')\n .option('--content <content>', 'Content body')\n .option('-f, --file <file>', 'Read content from file')\n .option('--stdin', 'Read content from stdin')\n .option('--overwrite', 'Overwrite if exists')\n .option('--no-index', 'Skip qmd index update (auto-updates by default)')\n .option('--embed', 'Also update qmd embeddings for vector search')\n .option('-v, --vault <path>', 'Vault path (default: find nearest)')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n \n let content = options.content || '';\n \n if (options.file) {\n content = fs.readFileSync(options.file, 'utf-8');\n } else if (options.stdin) {\n content = fs.readFileSync(0, 'utf-8');\n }\n \n const doc = await vault.store({\n category: options.category,\n title: options.title,\n content,\n overwrite: options.overwrite\n });\n \n console.log(chalk.green(`\u2713 Stored: ${doc.id}`));\n console.log(chalk.dim(` Path: ${doc.path}`));\n \n // Auto-update qmd index unless --no-index\n if (options.index !== false) {\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n if (options.embed) {\n await runQmd(collection ? ['embed', '-c', collection] : ['embed']);\n }\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === CAPTURE ===\nprogram\n .command('capture <note>')\n .description('Quick capture to inbox')\n .option('-t, --title <title>', 'Note title')\n .option('-v, --vault <path>', 'Vault path')\n .option('--no-index', 'Skip qmd index update')\n .action(async (note, options) => {\n try {\n const vault = await getVault(options.vault);\n const doc = await vault.capture(note, options.title);\n console.log(chalk.green(`\u2713 Captured: ${doc.id}`));\n \n // Auto-update qmd index unless --no-index\n if (options.index !== false) {\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SEARCH ===\nprogram\n .command('search <query>')\n .description('Search the vault via qmd (BM25)')\n .option('-n, --limit <n>', 'Max results', '10')\n .option('-c, --category <category>', 'Filter by category')\n .option('--tags <tags>', 'Filter by tags (comma-separated)')\n .option('--full', 'Include full content in results')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (query, options) => {\n try {\n const vault = await getVault(options.vault);\n \n const results = await vault.find(query, {\n limit: parseInt(options.limit),\n category: options.category,\n tags: options.tags?.split(',').map(t => t.trim()),\n fullContent: options.full\n });\n \n if (options.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n \n if (results.length === 0) {\n console.log(chalk.yellow('No results found.'));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83d\udd0d Found ${results.length} result(s) for \"${query}\":\\n`));\n \n for (const result of results) {\n const scoreBar = '\u2588'.repeat(Math.round(result.score * 10)).padEnd(10, '\u2591');\n console.log(chalk.green(`\ud83d\udcc4 ${result.document.title}`));\n console.log(chalk.dim(` ${result.document.category}/${result.document.id.split('/').pop()}`));\n console.log(chalk.dim(` Score: ${scoreBar} ${(result.score * 100).toFixed(0)}%`));\n if (result.snippet) {\n console.log(chalk.white(` ${result.snippet.split('\\n')[0].slice(0, 80)}...`));\n }\n console.log();\n }\n } catch (err) {\n if (err instanceof QmdUnavailableError) {\n printQmdMissing();\n process.exit(1);\n }\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === VSEARCH (qmd semantic search) ===\nprogram\n .command('vsearch <query>')\n .description('Semantic search via qmd (requires qmd installed)')\n .option('-n, --limit <n>', 'Max results', '5')\n .option('-c, --category <category>', 'Filter by category')\n .option('--tags <tags>', 'Filter by tags (comma-separated)')\n .option('--full', 'Include full content in results')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (query, options) => {\n try {\n const vault = await getVault(options.vault);\n \n const results = await vault.vsearch(query, {\n limit: parseInt(options.limit),\n category: options.category,\n tags: options.tags?.split(',').map(t => t.trim()),\n fullContent: options.full\n });\n \n if (options.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n \n if (results.length === 0) {\n console.log(chalk.yellow('No results found.'));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83e\udde0 Found ${results.length} result(s) for \"${query}\":\\n`));\n \n for (const result of results) {\n const scoreBar = '\u2588'.repeat(Math.round(result.score * 10)).padEnd(10, '\u2591');\n console.log(chalk.green(`\ud83d\udcc4 ${result.document.title}`));\n console.log(chalk.dim(` ${result.document.category}/${result.document.id.split('/').pop()}`));\n console.log(chalk.dim(` Score: ${scoreBar} ${(result.score * 100).toFixed(0)}%`));\n if (result.snippet) {\n console.log(chalk.white(` ${result.snippet.split('\\n')[0].slice(0, 80)}...`));\n }\n console.log();\n }\n } catch (err) {\n if (err instanceof QmdUnavailableError) {\n printQmdMissing();\n process.exit(1);\n }\n console.error(chalk.red(`Error: ${err.message}`));\n console.log(chalk.dim(`\\nTip: Install qmd: ${QMD_INSTALL_COMMAND}`));\n process.exit(1);\n }\n });\n\n// === LIST ===\nprogram\n .command('list [category]')\n .description('List documents')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (category, options) => {\n try {\n const vault = await getVault(options.vault);\n const docs = await vault.list(category);\n \n if (options.json) {\n console.log(JSON.stringify(docs.map(d => ({\n id: d.id,\n title: d.title,\n category: d.category,\n tags: d.tags,\n modified: d.modified\n })), null, 2));\n return;\n }\n \n if (docs.length === 0) {\n console.log(chalk.yellow('No documents found.'));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83d\udcda ${docs.length} document(s)${category ? ` in ${category}` : ''}:\\n`));\n \n // Group by category\n const grouped = {};\n for (const doc of docs) {\n grouped[doc.category] = grouped[doc.category] || [];\n grouped[doc.category].push(doc);\n }\n \n for (const [cat, catDocs] of Object.entries(grouped)) {\n console.log(chalk.yellow(`${cat}/`));\n for (const doc of catDocs) {\n console.log(chalk.dim(` - ${doc.title}`));\n }\n }\n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === GET ===\nprogram\n .command('get <id>')\n .description('Get a document by ID')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (id, options) => {\n try {\n const vault = await getVault(options.vault);\n const doc = await vault.get(id);\n \n if (!doc) {\n console.error(chalk.red(`Document not found: ${id}`));\n process.exit(1);\n }\n \n if (options.json) {\n console.log(JSON.stringify(doc, null, 2));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83d\udcc4 ${doc.title}\\n`));\n console.log(chalk.dim(`Category: ${doc.category}`));\n console.log(chalk.dim(`Path: ${doc.path}`));\n console.log(chalk.dim(`Tags: ${doc.tags.join(', ') || 'none'}`));\n console.log(chalk.dim(`Links: ${doc.links.join(', ') || 'none'}`));\n console.log(chalk.dim(`Modified: ${doc.modified.toISOString()}`));\n console.log(chalk.dim('---'));\n console.log(doc.content);\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === STATS ===\nprogram\n .command('stats')\n .description('Show vault statistics')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n const stats = await vault.stats();\n \n if (options.json) {\n console.log(JSON.stringify(stats, null, 2));\n return;\n }\n \n console.log(chalk.cyan(`\\n\ud83d\udc18 ${vault.getName()} Stats\\n`));\n console.log(chalk.dim(`Path: ${vault.getPath()}`));\n console.log(`Documents: ${chalk.green(stats.documents)}`);\n console.log(`Links: ${chalk.blue(stats.links)}`);\n console.log(`Tags: ${chalk.yellow(stats.tags.length)}`);\n console.log();\n console.log(chalk.dim('By category:'));\n for (const [cat, count] of Object.entries(stats.categories)) {\n console.log(chalk.dim(` ${cat}: ${count}`));\n }\n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SYNC ===\nprogram\n .command('sync <target>')\n .description('Sync vault to another location (e.g., for Obsidian)')\n .option('--delete', 'Delete orphan files in target')\n .option('--dry-run', \"Show what would be synced without syncing\")\n .option('-v, --vault <path>', 'Vault path')\n .action(async (target, options) => {\n try {\n const vault = await getVault(options.vault);\n \n console.log(chalk.cyan(`\\n\ud83d\udd04 Syncing to ${target}...\\n`));\n \n const result = await vault.sync({\n target,\n deleteOrphans: options.delete,\n dryRun: options.dryRun\n });\n \n if (options.dryRun) {\n console.log(chalk.yellow('DRY RUN - no changes made\\n'));\n }\n \n if (result.copied.length > 0) {\n console.log(chalk.green(`Copied: ${result.copied.length} files`));\n for (const f of result.copied.slice(0, 5)) {\n console.log(chalk.dim(` + ${f}`));\n }\n if (result.copied.length > 5) {\n console.log(chalk.dim(` ... and ${result.copied.length - 5} more`));\n }\n }\n \n if (result.deleted.length > 0) {\n console.log(chalk.red(`Deleted: ${result.deleted.length} files`));\n }\n \n if (result.unchanged.length > 0) {\n console.log(chalk.dim(`Unchanged: ${result.unchanged.length} files`));\n }\n \n if (result.errors.length > 0) {\n console.log(chalk.red(`\\nErrors:`));\n for (const e of result.errors) {\n console.log(chalk.red(` ${e}`));\n }\n }\n \n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === REINDEX ===\nprogram\n .command('reindex')\n .description('Rebuild the search index')\n .option('-v, --vault <path>', 'Vault path')\n .option('--qmd', 'Also update qmd embeddings')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n \n console.log(chalk.cyan('\\n\ud83d\udd04 Reindexing...\\n'));\n \n const count = await vault.reindex();\n console.log(chalk.green(`\u2713 Indexed ${count} documents`));\n \n if (options.qmd) {\n console.log(chalk.cyan('Updating qmd embeddings...'));\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n console.log(chalk.green('\u2713 qmd updated'));\n }\n \n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === REMEMBER (type-based storage) ===\nprogram\n .command('remember <type> <title>')\n .description('Store a memory with type classification (fact|feeling|decision|lesson|commitment|preference|relationship|project)')\n .option('--content <content>', 'Content body')\n .option('-f, --file <file>', 'Read content from file')\n .option('--stdin', 'Read content from stdin')\n .option('-v, --vault <path>', 'Vault path')\n .option('--no-index', 'Skip qmd index update')\n .action(async (type, title, options) => {\n const validTypes = ['fact', 'feeling', 'decision', 'lesson', 'commitment', 'preference', 'relationship', 'project'];\n if (!validTypes.includes(type)) {\n console.error(chalk.red(`Invalid type: ${type}`));\n console.error(chalk.dim(`Valid types: ${validTypes.join(', ')}`));\n process.exit(1);\n }\n \n try {\n const vault = await getVault(options.vault);\n \n let content = options.content || '';\n if (options.file) {\n content = fs.readFileSync(options.file, 'utf-8');\n } else if (options.stdin) {\n content = fs.readFileSync(0, 'utf-8');\n }\n \n const doc = await vault.remember(type, title, content);\n console.log(chalk.green(`\u2713 Remembered (${type}): ${doc.id}`));\n \n // Auto-update qmd index unless --no-index\n if (options.index !== false) {\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === WAKE (session start) ===\nprogram\n .command('wake')\n .description('Start a session (recover + recap + summary)')\n .option('-n, --handoff-limit <n>', 'Number of recent handoffs to include', '3')\n .option('--full', 'Show full recap (default: brief)')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (options) => {\n try {\n const vaultPath = resolveVaultPath(options.vault);\n const { wake } = await import('../dist/commands/wake.js');\n const { formatRecoveryInfo } = await import('../dist/commands/recover.js');\n const result = await wake({\n vaultPath,\n handoffLimit: parseInt(options.handoffLimit),\n brief: !options.full\n });\n\n console.log(chalk.cyan('\\n\ud83c\udf05 ClawVault Wake\\n'));\n console.log(formatRecoveryInfo(result.recovery));\n console.log();\n console.log(chalk.cyan('Recap'));\n console.log(result.recapMarkdown.trim());\n console.log();\n console.log(chalk.green(`You were working on: ${result.summary}`));\n\n process.exitCode = result.recovery.died ? 1 : 0;\n } catch (err) {\n if (err instanceof QmdUnavailableError) {\n printQmdMissing();\n process.exit(1);\n }\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SLEEP (session end) ===\nprogram\n .command('sleep <summary>')\n .description('End a session with a handoff (and optional git commit)')\n .option('-n, --next <items>', 'Next steps (comma-separated)')\n .option('-b, --blocked <items>', 'Blocked items (comma-separated)')\n .option('-d, --decisions <items>', 'Key decisions made (comma-separated)')\n .option('-q, --questions <items>', 'Open questions (comma-separated)')\n .option('-f, --feeling <state>', 'Emotional/energy state')\n .option('-s, --session <key>', 'Session key')\n .option('--index', 'Update qmd index after handoff')\n .option('--no-git', 'Skip git commit prompt')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (summary, options) => {\n try {\n const vaultPath = resolveVaultPath(options.vault);\n const { sleep } = await import('../dist/commands/sleep.js');\n const result = await sleep({\n workingOn: summary,\n next: options.next,\n blocked: options.blocked,\n decisions: options.decisions,\n questions: options.questions,\n feeling: options.feeling,\n sessionKey: options.session,\n vaultPath,\n index: options.index,\n git: options.git\n });\n\n console.log(chalk.green(`\u2713 Handoff saved: ${result.document.id}`));\n console.log(chalk.dim(` Path: ${result.document.path}`));\n console.log(chalk.dim(` Working on: ${result.handoff.workingOn.join(', ')}`));\n if (result.handoff.nextSteps.length > 0) {\n console.log(chalk.dim(` Next: ${result.handoff.nextSteps.join(', ')}`));\n } else {\n console.log(chalk.dim(' Next: (none)'));\n }\n if (result.handoff.blocked.length > 0) {\n console.log(chalk.dim(` Blocked: ${result.handoff.blocked.join(', ')}`));\n } else {\n console.log(chalk.dim(' Blocked: (none)'));\n }\n if (result.handoff.decisions?.length) {\n console.log(chalk.dim(` Decisions: ${result.handoff.decisions.join(', ')}`));\n }\n if (result.handoff.openQuestions?.length) {\n console.log(chalk.dim(` Questions: ${result.handoff.openQuestions.join(', ')}`));\n }\n if (result.handoff.feeling) {\n console.log(chalk.dim(` Feeling: ${result.handoff.feeling}`));\n }\n if (options.index) {\n console.log(chalk.dim(' qmd: index updated'));\n }\n if (result.git) {\n if (result.git.committed) {\n console.log(chalk.green(`\u2713 Git commit created${result.git.message ? `: ${result.git.message}` : ''}`));\n } else if (result.git.skippedReason === 'clean') {\n console.log(chalk.dim(' Git: clean'));\n } else if (result.git.skippedReason === 'declined') {\n console.log(chalk.dim(' Git: commit skipped'));\n }\n }\n } catch (err) {\n if (err instanceof QmdUnavailableError) {\n printQmdMissing();\n process.exit(1);\n }\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === HANDOFF (session bridge) ===\nprogram\n .command('handoff')\n .description('Create a session handoff document')\n .requiredOption('-w, --working-on <items>', 'What I was working on (comma-separated)')\n .option('-b, --blocked <items>', 'What is blocked (comma-separated)')\n .option('-n, --next <items>', 'What comes next (comma-separated)')\n .option('-d, --decisions <items>', 'Key decisions made (comma-separated)')\n .option('-q, --questions <items>', 'Open questions (comma-separated)')\n .option('-f, --feeling <state>', 'Emotional/energy state')\n .option('-s, --session <key>', 'Session key')\n .option('-v, --vault <path>', 'Vault path')\n .option('--no-index', 'Skip qmd index update (auto-updates by default)')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n \n const handoff = {\n workingOn: options.workingOn.split(',').map(s => s.trim()),\n blocked: options.blocked ? options.blocked.split(',').map(s => s.trim()) : [],\n nextSteps: options.next ? options.next.split(',').map(s => s.trim()) : [],\n decisions: options.decisions ? options.decisions.split(',').map(s => s.trim()) : undefined,\n openQuestions: options.questions ? options.questions.split(',').map(s => s.trim()) : undefined,\n feeling: options.feeling,\n sessionKey: options.session\n };\n \n const doc = await vault.createHandoff(handoff);\n \n if (options.json) {\n console.log(JSON.stringify({ id: doc.id, path: doc.path, handoff }, null, 2));\n } else {\n console.log(chalk.green(`\u2713 Handoff created: ${doc.id}`));\n console.log(chalk.dim(` Path: ${doc.path}`));\n }\n \n // Auto-update qmd index unless --no-index\n if (options.index !== false) {\n const collection = vault.getQmdCollection();\n await runQmd(collection ? ['update', '-c', collection] : ['update']);\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === RECAP (session bootstrap) ===\nprogram\n .command('recap')\n .description('Generate a session recap - who I was (bootstrap hook)')\n .option('-n, --handoff-limit <n>', 'Number of recent handoffs to include', '3')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .option('--markdown', 'Output as markdown (default)')\n .option('--brief', 'Minimal output for token savings')\n .action(async (options) => {\n try {\n const vault = await getVault(options.vault);\n \n const recap = await vault.generateRecap({\n handoffLimit: parseInt(options.handoffLimit),\n brief: options.brief\n });\n \n if (options.json) {\n console.log(JSON.stringify(recap, null, 2));\n return;\n }\n \n // Output as markdown (default)\n const md = vault.formatRecap(recap, { brief: options.brief });\n console.log(md);\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === SHELL INIT ===\nprogram\n .command('shell-init')\n .description('Output shell integration for ClawVault')\n .action(async () => {\n try {\n const { shellInit } = await import('../dist/commands/shell-init.js');\n console.log(shellInit());\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === TEMPLATE ===\nconst template = program\n .command('template')\n .description('Manage templates');\n\ntemplate\n .command('list')\n .description('List available templates')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (options) => {\n try {\n const { listTemplates } = await import('../dist/commands/template.js');\n const templates = listTemplates({ vaultPath: options.vault });\n if (templates.length === 0) {\n console.log(chalk.yellow('No templates found.'));\n return;\n }\n console.log(chalk.cyan('\\n\ud83d\udcc4 Templates:\\n'));\n for (const name of templates) {\n console.log(`- ${name}`);\n }\n console.log();\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\ntemplate\n .command('create <name>')\n .description('Create a file from a template')\n .option('-t, --title <title>', 'Document title')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (name, options) => {\n try {\n const { createFromTemplate } = await import('../dist/commands/template.js');\n const result = createFromTemplate(name, {\n title: options.title,\n vaultPath: options.vault\n });\n console.log(chalk.green(`\u2713 Created from template: ${name}`));\n console.log(chalk.dim(` Output: ${result.outputPath}`));\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\ntemplate\n .command('add <file>')\n .description('Add a custom template')\n .requiredOption('--name <name>', 'Template name')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (file, options) => {\n try {\n const { addTemplate } = await import('../dist/commands/template.js');\n const result = addTemplate(file, {\n name: options.name,\n vaultPath: options.vault\n });\n console.log(chalk.green(`\u2713 Template added: ${result.name}`));\n console.log(chalk.dim(` Path: ${result.templatePath}`));\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === DOCTOR (health check) ===\nprogram\n .command('doctor')\n .description('Check ClawVault setup health')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (options) => {\n try {\n const { doctor } = await import('../dist/commands/doctor.js');\n const report = await doctor(options.vault);\n\n console.log(chalk.cyan('\\n\ud83e\ude7a ClawVault Health Check\\n'));\n if (report.vaultPath) {\n console.log(chalk.dim(`Vault: ${report.vaultPath}`));\n console.log();\n }\n\n for (const check of report.checks) {\n const prefix = check.status === 'ok'\n ? chalk.green('\u2713')\n : check.status === 'warn'\n ? chalk.yellow('\u26a0')\n : chalk.red('\u2717');\n const detail = check.detail ? ` \u2014 ${check.detail}` : '';\n console.log(`${prefix} ${check.label}${detail}`);\n if (check.hint) {\n console.log(chalk.dim(` ${check.hint}`));\n }\n }\n\n const issues = report.warnings + report.errors;\n console.log();\n if (issues === 0) {\n console.log(chalk.green('\u2705 ClawVault is healthy!\\n'));\n } else {\n console.log(chalk.yellow(`\u26a0 ${issues} issue(s) found\\n`));\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === ENTITIES ===\nprogram\n .command('entities')\n .description('List all linkable entities in the vault')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { entitiesCommand } = await import('../dist/commands/entities.js');\n await entitiesCommand({ json: options.json });\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === LINK ===\nprogram\n .command('link [file]')\n .description('Auto-link entity mentions in markdown files')\n .option('--all', 'Link all files in vault')\n .option('--backlinks <file>', 'Show backlinks to a file')\n .option('--dry-run', 'Show what would be linked without changing files')\n .option('--orphans', 'List broken wiki-links')\n .option('--rebuild', 'Rebuild backlinks index')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (file, options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { linkCommand } = await import('../dist/commands/link.js');\n await linkCommand(file, {\n all: options.all,\n dryRun: options.dryRun,\n backlinks: options.backlinks,\n orphans: options.orphans,\n rebuild: options.rebuild\n });\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === CHECKPOINT ===\nprogram\n .command('checkpoint')\n .description('Quick state checkpoint for context death resilience')\n .option('--working-on <text>', 'What you are currently working on')\n .option('--focus <text>', 'Current focus area')\n .option('--blocked <text>', 'What is blocking progress')\n .option('--urgent', 'Trigger OpenClaw wake after checkpoint')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { checkpoint } = await import('../dist/commands/checkpoint.js');\n const data = await checkpoint({\n vaultPath: path.resolve(vaultPath),\n workingOn: options.workingOn,\n focus: options.focus,\n blocked: options.blocked,\n urgent: options.urgent\n });\n \n if (options.json) {\n console.log(JSON.stringify(data, null, 2));\n } else {\n console.log(chalk.green('\u2713 Checkpoint saved'));\n console.log(chalk.dim(` Timestamp: ${data.timestamp}`));\n if (data.workingOn) console.log(chalk.dim(` Working on: ${data.workingOn}`));\n if (data.focus) console.log(chalk.dim(` Focus: ${data.focus}`));\n if (data.blocked) console.log(chalk.dim(` Blocked: ${data.blocked}`));\n if (data.urgent) console.log(chalk.dim(' Urgent: yes'));\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === RECOVER ===\nprogram\n .command('recover')\n .description('Check for context death and recover state')\n .option('--clear', 'Clear the dirty death flag after recovery')\n .option('--verbose', 'Show full checkpoint and handoff content')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { recover, formatRecoveryInfo } = await import('../dist/commands/recover.js');\n const info = await recover(path.resolve(vaultPath), {\n clearFlag: options.clear,\n verbose: options.verbose\n });\n \n if (options.json) {\n console.log(JSON.stringify(info, null, 2));\n } else {\n console.log(formatRecoveryInfo(info, { verbose: options.verbose }));\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === STATUS ===\nprogram\n .command('status')\n .description('Show vault health and status')\n .option('-v, --vault <path>', 'Vault path')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n\n const { statusCommand } = await import('../dist/commands/status.js');\n await statusCommand(path.resolve(vaultPath), { json: options.json });\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === CLEAN-EXIT ===\nprogram\n .command('clean-exit')\n .description('Mark session as cleanly exited (clears dirty death flag)')\n .option('-v, --vault <path>', 'Vault path')\n .action(async (options) => {\n try {\n const vaultPath = options.vault || process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n console.error(chalk.red('Error: No vault path. Set CLAWVAULT_PATH or use -v'));\n process.exit(1);\n }\n \n const { cleanExit } = await import('../dist/commands/checkpoint.js');\n await cleanExit(path.resolve(vaultPath));\n console.log(chalk.green('\u2713 Clean exit recorded'));\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// === REPAIR-SESSION ===\nprogram\n .command('repair-session')\n .description('Repair corrupted OpenClaw session transcripts')\n .option('-s, --session <id>', 'Session ID (defaults to current main session)')\n .option('-a, --agent <id>', 'Agent ID (defaults to configured agent)')\n .option('--backup', 'Create backup before repair (default: true)', true)\n .option('--no-backup', 'Skip backup creation')\n .option('--dry-run', 'Show what would be repaired without writing')\n .option('--list', 'List available sessions')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const {\n repairSessionCommand,\n formatRepairResult,\n listAgentSessions\n } = await import('../dist/commands/repair-session.js');\n \n // List mode\n if (options.list) {\n console.log(listAgentSessions(options.agent));\n return;\n }\n \n const result = await repairSessionCommand({\n sessionId: options.session,\n agentId: options.agent,\n backup: options.backup,\n dryRun: options.dryRun\n });\n \n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatRepairResult(result, { dryRun: options.dryRun }));\n }\n \n // Exit with code 1 if corruption was found but not fixed (dry-run)\n if (result.corruptedEntries.length > 0 && !result.repaired) {\n process.exit(1);\n }\n } catch (err) {\n console.error(chalk.red(`Error: ${err.message}`));\n process.exit(1);\n }\n });\n\n// Parse and run\nprogram.parse();\n",606 "inputSchema": {},607 "outputSchema": null,608 "icons": null,609 "annotations": null,610 "meta": null,611 "execution": null612 },613 {614 "name": "handler.js",615 "title": null,616 "description": "Script: handler.js. Code:\n/**\n * ClawVault OpenClaw Hook\n * \n * Provides automatic context death resilience:\n * - gateway:startup \u2192 detect context death, inject recovery info\n * - command:new \u2192 auto-checkpoint before session reset\n * \n * SECURITY: Uses execFileSync (no shell) to prevent command injection\n */\n\nimport { execFileSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// Sanitize string for safe display (prevent prompt injection via control chars)\nfunction sanitizeForDisplay(str) {\n if (typeof str !== 'string') return '';\n // Remove control characters, limit length, escape markdown\n return str\n .replace(/[\\x00-\\x1f\\x7f]/g, '') // Remove control chars\n .replace(/[`*_~\\[\\]]/g, '\\\\$&') // Escape markdown\n .slice(0, 200); // Limit length\n}\n\n// Validate vault path - must be absolute and exist\nfunction validateVaultPath(vaultPath) {\n if (!vaultPath || typeof vaultPath !== 'string') return null;\n \n // Resolve to absolute path\n const resolved = path.resolve(vaultPath);\n \n // Must be absolute\n if (!path.isAbsolute(resolved)) return null;\n \n // Must exist and be a directory\n try {\n const stat = fs.statSync(resolved);\n if (!stat.isDirectory()) return null;\n } catch {\n return null;\n }\n \n // Must contain .clawvault.json\n const configPath = path.join(resolved, '.clawvault.json');\n if (!fs.existsSync(configPath)) return null;\n \n return resolved;\n}\n\n// Find vault by walking up directories\nfunction findVaultPath() {\n // Check env first\n if (process.env.CLAWVAULT_PATH) {\n return validateVaultPath(process.env.CLAWVAULT_PATH);\n }\n\n // Walk up from cwd\n let dir = process.cwd();\n const root = path.parse(dir).root;\n \n while (dir !== root) {\n const validated = validateVaultPath(dir);\n if (validated) return validated;\n \n // Also check memory/ subdirectory (OpenClaw convention)\n const memoryDir = path.join(dir, 'memory');\n const memoryValidated = validateVaultPath(memoryDir);\n if (memoryValidated) return memoryValidated;\n \n dir = path.dirname(dir);\n }\n \n return null;\n}\n\n// Run clawvault command safely (no shell)\nfunction runClawvault(args) {\n try {\n // Use execFileSync to avoid shell injection\n // Arguments are passed as array, not interpolated into shell\n const output = execFileSync('clawvault', args, {\n encoding: 'utf-8',\n timeout: 15000,\n stdio: ['pipe', 'pipe', 'pipe'],\n // Explicitly no shell\n shell: false\n });\n return { success: true, output: output.trim(), code: 0 };\n } catch (err) {\n return { \n success: false, \n output: err.stderr?.toString() || err.message || String(err),\n code: err.status || 1\n };\n }\n}\n\n// Parse recovery output safely\nfunction parseRecoveryOutput(output) {\n if (!output || typeof output !== 'string') {\n return { hadDeath: false, workingOn: null };\n }\n \n const hadDeath = output.includes('Context death detected') || \n output.includes('died') || \n output.includes('\u26a0\ufe0f');\n \n let workingOn = null;\n if (hadDeath) {\n const lines = output.split('\\n');\n const workingOnLine = lines.find(l => l.toLowerCase().includes('working on'));\n if (workingOnLine) {\n const parts = workingOnLine.split(':');\n if (parts.length > 1) {\n workingOn = sanitizeForDisplay(parts.slice(1).join(':').trim());\n }\n }\n }\n \n return { hadDeath, workingOn };\n}\n\n// Handle gateway startup - check for context death\nasync function handleStartup(event) {\n const vaultPath = findVaultPath();\n if (!vaultPath) {\n console.log('[clawvault] No vault found, skipping recovery check');\n return;\n }\n\n console.log(`[clawvault] Checking for context death`);\n\n // Pass vault path as separate argument (not interpolated)\n const result = runClawvault(['recover', '--clear', '-v', vaultPath]);\n \n if (!result.success) {\n console.warn('[clawvault] Recovery check failed');\n return;\n }\n\n const { hadDeath, workingOn } = parseRecoveryOutput(result.output);\n \n if (hadDeath) {\n // Build safe alert message with sanitized content\n const alertParts = ['[ClawVault] Context death detected.'];\n if (workingOn) {\n alertParts.push(`Last working on: ${workingOn}`);\n }\n alertParts.push('Run `clawvault wake` for full recovery context.');\n \n const alertMsg = alertParts.join(' ');\n\n // Inject into event messages if available\n if (event.messages && Array.isArray(event.messages)) {\n event.messages.push(alertMsg);\n }\n \n console.warn('[clawvault] Context death detected, alert injected');\n } else {\n console.log('[clawvault] Clean startup - no context death');\n }\n}\n\n// Handle /new command - auto-checkpoint before reset\nasync function handleNew(event) {\n const vaultPath = findVaultPath();\n if (!vaultPath) {\n console.log('[clawvault] No vault found, skipping auto-checkpoint');\n return;\n }\n\n // Sanitize session info for checkpoint\n const sessionKey = typeof event.sessionKey === 'string' \n ? event.sessionKey.replace(/[^a-zA-Z0-9:_-]/g, '').slice(0, 100)\n : 'unknown';\n const source = typeof event.context?.commandSource === 'string'\n ? event.context.commandSource.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 50)\n : 'cli';\n\n console.log('[clawvault] Auto-checkpoint before /new');\n\n // Pass each argument separately (no shell interpolation)\n const result = runClawvault([\n 'checkpoint',\n '--working-on', `Session reset via /new from ${source}`,\n '--focus', `Pre-reset checkpoint, session: ${sessionKey}`,\n '-v', vaultPath\n ]);\n\n if (result.success) {\n console.log('[clawvault] Auto-checkpoint created');\n } else {\n console.warn('[clawvault] Auto-checkpoint failed');\n }\n}\n\n// Main handler - route events\nconst handler = async (event) => {\n try {\n if (event.type === 'gateway' && event.action === 'startup') {\n await handleStartup(event);\n return;\n }\n\n if (event.type === 'command' && event.action === 'new') {\n await handleNew(event);\n return;\n }\n } catch (err) {\n console.error('[clawvault] Hook error:', err.message || 'unknown error');\n }\n};\n\nexport default handler;\n",617 "inputSchema": {},618 "outputSchema": null,619 "icons": null,620 "annotations": null,621 "meta": null,622 "execution": null623 },624 {625 "name": "index.d.ts",626 "title": null,627 "description": "Script: index.d.ts. Code:\nimport { V as VaultConfig, S as StoreOptions, D as Document, a as SearchOptions, b as SearchResult, c as SyncOptions, d as SyncResult, C as Category, M as MemoryType, H as HandoffDocument, e as SessionRecap } from './types-DO8rJ490.js';\nexport { f as DEFAULT_CATEGORIES, g as DEFAULT_CONFIG, h as MEMORY_TYPES, T as TYPE_TO_CATEGORY, i as VaultMeta } from './types-DO8rJ490.js';\nexport { setupCommand } from './commands/setup.js';\nexport { TemplateVariables, buildTemplateVariables, renderTemplate } from './lib/template-engine.js';\n\n/**\n * ClawVault - The elephant's memory\n */\n\ndeclare class ClawVault {\n private config;\n private search;\n private initialized;\n constructor(vaultPath: string);\n /**\n * Initialize a new vault\n */\n init(options?: Partial<VaultConfig>): Promise<void>;\n /**\n * Load an existing vault\n */\n load(): Promise<void>;\n /**\n * Reindex all documents\n */\n reindex(): Promise<number>;\n /**\n * Load a document from disk\n */\n private loadDocument;\n /**\n * Store a new document\n */\n store(options: StoreOptions): Promise<Document>;\n /**\n * Quick store to inbox\n */\n capture(note: string, title?: string): Promise<Document>;\n /**\n * Search the vault (BM25 via qmd)\n */\n find(query: string, options?: SearchOptions): Promise<SearchResult[]>;\n /**\n * Semantic/vector search (via qmd vsearch)\n */\n vsearch(query: string, options?: SearchOptions): Promise<SearchResult[]>;\n /**\n * Combined search with query expansion (via qmd query)\n */\n query(query: string, options?: SearchOptions): Promise<SearchResult[]>;\n /**\n * Get a document by ID or path\n */\n get(idOrPath: string): Promise<Document | null>;\n /**\n * List documents in a category\n */\n list(category?: string): Promise<Document[]>;\n /**\n * Sync vault to another location (for Obsidian on Windows, etc.)\n */\n sync(options: SyncOptions): Promise<SyncResult>;\n /**\n * Get vault statistics\n */\n stats(): Promise<{\n documents: number;\n categories: {\n [key: string]: number;\n };\n links: number;\n tags: string[];\n }>;\n /**\n * Get all categories\n */\n getCategories(): Category[];\n /**\n * Check if vault is initialized\n */\n isInitialized(): boolean;\n /**\n * Get vault path\n */\n getPath(): string;\n /**\n * Get vault name\n */\n getName(): string;\n /**\n * Get qmd collection name\n */\n getQmdCollection(): string;\n /**\n * Get qmd collection root\n */\n getQmdRoot(): string;\n /**\n * Store a memory with type classification\n * Automatically routes to correct category based on type\n */\n remember(type: MemoryType, title: string, content: string, frontmatter?: Record<string, unknown>): Promise<Document>;\n /**\n * Create a session handoff document\n * Call this before context death or long pauses\n */\n createHandoff(handoff: Omit<HandoffDocument, 'created'>): Promise<Document>;\n /**\n * Format handoff as readable markdown\n */\n private formatHandoff;\n /**\n * Generate a session recap - who I was\n * Call this on bootstrap to restore context\n */\n generateRecap(options?: {\n handoffLimit?: number;\n brief?: boolean;\n }): Promise<SessionRecap>;\n /**\n * Format recap as readable markdown for injection\n */\n formatRecap(recap: SessionRecap, options?: {\n brief?: boolean;\n }): string;\n /**\n * Parse a handoff document back into structured form\n */\n private parseHandoff;\n private applyQmdConfig;\n private slugify;\n private saveIndex;\n private createTemplates;\n private generateReadme;\n private getCategoryDescription;\n}\n/**\n * Find and open the nearest vault (walks up directory tree)\n */\ndeclare function findVault(startPath?: string): Promise<ClawVault | null>;\n/**\n * Create a new vault\n */\ndeclare function createVault(vaultPath: string, options?: Partial<VaultConfig>): Promise<ClawVault>;\n\n/**\n * ClawVault Search Engine - qmd Backend\n * Uses qmd CLI for BM25 and vector search\n */\n\ndeclare const QMD_INSTALL_URL = \"https://github.com/tobi/qmd\";\ndeclare const QMD_INSTALL_COMMAND = \"bun install -g github:tobi/qmd\";\ndeclare class QmdUnavailableError extends Error {\n constructor(message?: string);\n}\n/**\n * Check if qmd is available\n */\ndeclare function hasQmd(): boolean;\n/**\n * Trigger qmd update (reindex)\n */\ndeclare function qmdUpdate(collection?: string): void;\n/**\n * Trigger qmd embed (create/update vector embeddings)\n */\ndeclare function qmdEmbed(collection?: string): void;\n/**\n * QMD Search Engine - wraps qmd CLI\n */\ndeclare class SearchEngine {\n private documents;\n private collection;\n private vaultPath;\n private collectionRoot;\n /**\n * Set the collection name (usually vault name)\n */\n setCollection(name: string): void;\n /**\n * Set the vault path for file resolution\n */\n setVaultPath(vaultPath: string): void;\n /**\n * Set the collection root for qmd:// URI resolution\n */\n setCollectionRoot(root: string): void;\n /**\n * Add or update a document in the local cache\n * Note: qmd indexing happens via qmd update command\n */\n addDocument(doc: Document): void;\n /**\n * Remove a document from the local cache\n */\n removeDocument(id: string): void;\n /**\n * No-op for qmd - indexing is managed externally\n */\n rebuildIDF(): void;\n /**\n * BM25 search via qmd\n */\n search(query: string, options?: SearchOptions): SearchResult[];\n /**\n * Vector/semantic search via qmd vsearch\n */\n vsearch(query: string, options?: SearchOptions): SearchResult[];\n /**\n * Combined search with query expansion (qmd query command)\n */\n query(query: string, options?: SearchOptions): SearchResult[];\n private runQmdQuery;\n /**\n * Convert qmd results to ClawVault SearchResult format\n */\n private convertResults;\n /**\n * Convert qmd:// URI to file path\n */\n private qmdUriToPath;\n /**\n * Clean up qmd snippet format\n */\n private cleanSnippet;\n /**\n * Get all cached documents\n */\n getAllDocuments(): Document[];\n /**\n * Get document count\n */\n get size(): number;\n /**\n * Clear the local document cache\n */\n clear(): void;\n /**\n * Export documents for persistence\n */\n export(): {\n documents: Document[];\n };\n /**\n * Import from persisted data\n */\n import(data: {\n documents: Document[];\n }): void;\n}\n/**\n * Find wiki-links in content\n */\ndeclare function extractWikiLinks(content: string): string[];\n/**\n * Find tags in content (#tag format)\n */\ndeclare function extractTags(content: string): string[];\n\n/**\n * ClawVault \ud83d\udc18 \u2014 An Elephant Never Forgets\n *\n * Structured memory system for AI agents with Obsidian-compatible markdown\n * and embedded semantic search.\n *\n * @example\n * ```typescript\n * import { ClawVault, createVault, findVault } from 'clawvault';\n *\n * // Create a new vault\n * const vault = await createVault('./my-memory');\n *\n * // Store a memory\n * await vault.store({\n * category: 'decisions',\n * title: 'Use ClawVault',\n * content: 'Decided to use ClawVault for memory management.'\n * });\n *\n * // Search memories\n * const results = await vault.find('memory management');\n * console.log(results);\n * ```\n */\n\ndeclare const VERSION: string;\n\nexport { Category, ClawVault, Document, HandoffDocument, MemoryType, QMD_INSTALL_COMMAND, QMD_INSTALL_URL, QmdUnavailableError, SearchEngine, SearchOptions, SearchResult, SessionRecap, StoreOptions, SyncOptions, SyncResult, VERSION, VaultConfig, createVault, extractTags, extractWikiLinks, findVault, hasQmd, qmdEmbed, qmdUpdate };\n",628 "inputSchema": {},629 "outputSchema": null,630 "icons": null,631 "annotations": null,632 "meta": null,633 "execution": null634 },635 {636 "name": "chunk-L53L5FCL.js",637 "title": null,638 "description": "Script: chunk-L53L5FCL.js. Code:\n// src/lib/session-repair.ts\nimport * as fs from \"fs\";\nfunction parseTranscript(filePath) {\n const content = fs.readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((line) => line.trim());\n const entries = [];\n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i];\n try {\n const entry = JSON.parse(raw);\n entries.push({ line: i + 1, entry, raw });\n } catch {\n console.warn(`Warning: Could not parse line ${i + 1}`);\n }\n }\n return entries;\n}\nfunction extractToolUses(entries) {\n const toolUses = /* @__PURE__ */ new Map();\n for (const { line, entry } of entries) {\n if (entry.type !== \"message\") continue;\n if (entry.message?.role !== \"assistant\") continue;\n const isAborted = entry.message.stopReason === \"aborted\";\n const content = entry.message.content || [];\n for (const block of content) {\n if (block.type === \"toolCall\" || block.type === \"tool_use\" || block.type === \"functionCall\") {\n if (block.id) {\n const isPartial = !!block.partialJson;\n toolUses.set(block.id, {\n id: block.id,\n lineNumber: line,\n entryId: entry.id,\n isAborted: isAborted || isPartial,\n isPartial,\n name: block.name\n });\n }\n }\n }\n }\n return toolUses;\n}\nfunction findCorruptedEntries(entries, toolUses) {\n const corrupted = [];\n const entriesToRemove = /* @__PURE__ */ new Set();\n for (const [toolId, info] of toolUses) {\n if (info.isAborted) {\n corrupted.push({\n lineNumber: info.lineNumber,\n entryId: info.entryId,\n type: \"aborted_tool_use\",\n toolUseId: toolId,\n description: `Aborted tool_use${info.name ? ` (${info.name})` : \"\"} with id: ${toolId}`\n });\n entriesToRemove.add(info.entryId);\n }\n }\n for (const { line, entry } of entries) {\n if (entry.type !== \"message\") continue;\n if (entry.message?.role !== \"toolResult\") continue;\n const content = entry.message.content || [];\n let toolCallId;\n const msg = entry.message;\n toolCallId = msg.toolCallId || msg.toolUseId;\n if (!toolCallId) {\n for (const block of content) {\n if (block.toolCallId || block.toolUseId) {\n toolCallId = block.toolCallId || block.toolUseId;\n break;\n }\n }\n }\n if (!toolCallId) continue;\n const toolUse = toolUses.get(toolCallId);\n if (!toolUse || toolUse.isAborted) {\n corrupted.push({\n lineNumber: line,\n entryId: entry.id,\n type: \"orphaned_tool_result\",\n toolUseId: toolCallId,\n description: toolUse ? `Orphaned tool_result references aborted tool_use: ${toolCallId}` : `Orphaned tool_result references non-existent tool_use: ${toolCallId}`\n });\n entriesToRemove.add(entry.id);\n }\n }\n return { corrupted, entriesToRemove };\n}\nfunction computeParentRelinks(entries, entriesToRemove) {\n const relinks = [];\n const entryParents = /* @__PURE__ */ new Map();\n for (const { entry } of entries) {\n entryParents.set(entry.id, entry.parentId);\n }\n for (const { line, entry } of entries) {\n if (entriesToRemove.has(entry.id)) continue;\n if (!entry.parentId) continue;\n if (!entriesToRemove.has(entry.parentId)) continue;\n let newParentId = entry.parentId;\n while (newParentId && entriesToRemove.has(newParentId)) {\n newParentId = entryParents.get(newParentId) || null;\n }\n if (newParentId !== entry.parentId) {\n relinks.push({\n lineNumber: line,\n entryId: entry.id,\n oldParentId: entry.parentId,\n newParentId: newParentId || \"null\"\n });\n }\n }\n return relinks;\n}\nfunction analyzeSession(filePath) {\n const entries = parseTranscript(filePath);\n const sessionEntry = entries.find((e) => e.entry.type === \"session\");\n const sessionId = sessionEntry?.entry.id || \"unknown\";\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const parentRelinks = computeParentRelinks(entries, entriesToRemove);\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n repaired: false\n };\n}\nfunction repairSession(filePath, options = {}) {\n const { backup = true, dryRun = false } = options;\n const entries = parseTranscript(filePath);\n const sessionEntry = entries.find((e) => e.entry.type === \"session\");\n const sessionId = sessionEntry?.entry.id || \"unknown\";\n const toolUses = extractToolUses(entries);\n const { corrupted, entriesToRemove } = findCorruptedEntries(entries, toolUses);\n const parentRelinks = computeParentRelinks(entries, entriesToRemove);\n if (corrupted.length === 0) {\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: [],\n parentRelinks: [],\n removedCount: 0,\n relinkedCount: 0,\n repaired: false\n };\n }\n if (dryRun) {\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n repaired: false\n };\n }\n let backupPath;\n if (backup) {\n const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, \"\").replace(\"T\", \"-\").slice(0, 15);\n backupPath = `${filePath}.backup-${timestamp}`;\n fs.copyFileSync(filePath, backupPath);\n }\n const relinkMap = /* @__PURE__ */ new Map();\n for (const relink of parentRelinks) {\n relinkMap.set(relink.entryId, relink.newParentId === \"null\" ? null : relink.newParentId);\n }\n const repairedLines = [];\n for (const { entry, raw } of entries) {\n if (entriesToRemove.has(entry.id)) continue;\n if (relinkMap.has(entry.id)) {\n const newEntry = { ...entry, parentId: relinkMap.get(entry.id) };\n repairedLines.push(JSON.stringify(newEntry));\n } else {\n repairedLines.push(raw);\n }\n }\n fs.writeFileSync(filePath, repairedLines.join(\"\\n\") + \"\\n\");\n return {\n sessionId,\n totalLines: entries.length,\n corruptedEntries: corrupted,\n parentRelinks,\n removedCount: entriesToRemove.size,\n relinkedCount: parentRelinks.length,\n backupPath,\n repaired: true\n };\n}\n\nexport {\n parseTranscript,\n extractToolUses,\n findCorruptedEntries,\n computeParentRelinks,\n analyzeSession,\n repairSession\n};\n",639 "inputSchema": {},640 "outputSchema": null,641 "icons": null,642 "annotations": null,643 "meta": null,644 "execution": null645 },646 {647 "name": "chunk-7ZRP733D.js",648 "title": null,649 "description": "Script: chunk-7ZRP733D.js. Code:\n// src/lib/time.ts\nfunction formatAge(ms) {\n if (!Number.isFinite(ms)) return \"unknown\";\n const seconds = Math.max(0, Math.floor(ms / 1e3));\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n if (days > 0) return `${days}d ${hours % 24}h`;\n if (hours > 0) return `${hours}h ${minutes % 60}m`;\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\n}\n\nexport {\n formatAge\n};\n",650 "inputSchema": {},651 "outputSchema": null,652 "icons": null,653 "annotations": null,654 "meta": null,655 "execution": null656 },657 {658 "name": "template-engine.js",659 "title": null,660 "description": "Script: template-engine.js. Code:\nimport {\n buildTemplateVariables,\n renderTemplate\n} from \"../chunk-7766SIJP.js\";\nexport {\n buildTemplateVariables,\n renderTemplate\n};\n",661 "inputSchema": {},662 "outputSchema": null,663 "icons": null,664 "annotations": null,665 "meta": null,666 "execution": null667 },668 {669 "name": "entity-index.js",670 "title": null,671 "description": "Script: entity-index.js. Code:\nimport {\n buildEntityIndex,\n getSortedAliases\n} from \"../chunk-J7ZWCI2C.js\";\nexport {\n buildEntityIndex,\n getSortedAliases\n};\n",672 "inputSchema": {},673 "outputSchema": null,674 "icons": null,675 "annotations": null,676 "meta": null,677 "execution": null678 },679 {680 "name": "session-repair.d.ts",681 "title": null,682 "description": "Script: session-repair.d.ts. Code:\n/**\n * Session transcript repair logic\n *\n * Repairs corrupted OpenClaw session transcripts by:\n * 1. Finding aborted tool_use blocks (stopReason: \"aborted\", partialJson present)\n * 2. Finding orphaned tool_result messages that reference non-existent tool_use IDs\n * 3. Removing both the aborted entries and orphaned results\n * 4. Relinking parent chain references\n */\ninterface TranscriptEntry {\n type: 'session' | 'message' | 'compaction' | 'custom' | 'thinking_level_change' | string;\n id: string;\n parentId: string | null;\n timestamp: string;\n message?: {\n role: 'user' | 'assistant' | 'toolResult' | 'system';\n content: Array<{\n type: string;\n id?: string;\n name?: string;\n arguments?: unknown;\n toolCallId?: string;\n toolUseId?: string;\n partialJson?: string;\n text?: string;\n }>;\n stopReason?: string;\n errorMessage?: string;\n };\n summary?: string;\n customType?: string;\n data?: unknown;\n thinkingLevel?: string;\n}\ninterface ToolUseInfo {\n id: string;\n lineNumber: number;\n entryId: string;\n isAborted: boolean;\n isPartial: boolean;\n name?: string;\n}\ninterface CorruptedEntry {\n lineNumber: number;\n entryId: string;\n type: 'aborted_tool_use' | 'orphaned_tool_result';\n toolUseId: string;\n description: string;\n}\ninterface ParentRelink {\n lineNumber: number;\n entryId: string;\n oldParentId: string;\n newParentId: string;\n}\ninterface RepairResult {\n sessionId: string;\n totalLines: number;\n corruptedEntries: CorruptedEntry[];\n parentRelinks: ParentRelink[];\n removedCount: number;\n relinkedCount: number;\n backupPath?: string;\n repaired: boolean;\n}\n/**\n * Parse a JSONL file into transcript entries with line numbers\n */\ndeclare function parseTranscript(filePath: string): Array<{\n line: number;\n entry: TranscriptEntry;\n raw: string;\n}>;\n/**\n * Extract all tool_use IDs from assistant messages\n */\ndeclare function extractToolUses(entries: Array<{\n line: number;\n entry: TranscriptEntry;\n}>): Map<string, ToolUseInfo>;\n/**\n * Find orphaned tool_result messages that reference non-existent or aborted tool_use IDs\n */\ndeclare function findCorruptedEntries(entries: Array<{\n line: number;\n entry: TranscriptEntry;\n}>, toolUses: Map<string, ToolUseInfo>): {\n corrupted: CorruptedEntry[];\n entriesToRemove: Set<string>;\n};\n/**\n * Compute parent chain relinks after removing entries\n */\ndeclare function computeParentRelinks(entries: Array<{\n line: number;\n entry: TranscriptEntry;\n}>, entriesToRemove: Set<string>): ParentRelink[];\n/**\n * Analyze a session transcript for corruption without modifying it\n */\ndeclare function analyzeSession(filePath: string): RepairResult;\n/**\n * Repair a session transcript\n */\ndeclare function repairSession(filePath: string, options?: {\n backup?: boolean;\n dryRun?: boolean;\n}): RepairResult;\n\nexport { type CorruptedEntry, type ParentRelink, type RepairResult, type ToolUseInfo, type TranscriptEntry, analyzeSession, computeParentRelinks, extractToolUses, findCorruptedEntries, parseTranscript, repairSession };\n",683 "inputSchema": {},684 "outputSchema": null,685 "icons": null,686 "annotations": null,687 "meta": null,688 "execution": null689 },690 {691 "name": "entity-index.d.ts",692 "title": null,693 "description": "Script: entity-index.d.ts. Code:\ninterface EntityEntry {\n path: string;\n aliases: string[];\n}\ninterface EntityIndex {\n entries: Map<string, string>;\n byPath: Map<string, EntityEntry>;\n}\n/**\n * Build an entity index from all markdown files in the vault.\n * Extracts linkable names from:\n * - Filename (without .md)\n * - Frontmatter `title` field\n * - Frontmatter `aliases` array\n */\ndeclare function buildEntityIndex(vaultPath: string): EntityIndex;\n/**\n * Get all entities sorted by alias length (longest first)\n * This ensures \"Justin Dukes\" is matched before \"Justin\"\n */\ndeclare function getSortedAliases(index: EntityIndex): Array<{\n alias: string;\n path: string;\n}>;\n\nexport { type EntityEntry, type EntityIndex, buildEntityIndex, getSortedAliases };\n",694 "inputSchema": {},695 "outputSchema": null,696 "icons": null,697 "annotations": null,698 "meta": null,699 "execution": null700 },701 {702 "name": "session-utils.js",703 "title": null,704 "description": "Script: session-utils.js. Code:\nimport {\n backupSession,\n findMainSession,\n findSessionById,\n getOpenClawAgentsDir,\n getSessionFilePath,\n getSessionsDir,\n getSessionsJsonPath,\n listAgents,\n listSessions,\n loadSessionsStore\n} from \"../chunk-AZRV2I5U.js\";\nexport {\n backupSession,\n findMainSession,\n findSessionById,\n getOpenClawAgentsDir,\n getSessionFilePath,\n getSessionsDir,\n getSessionsJsonPath,\n listAgents,\n listSessions,\n loadSessionsStore\n};\n",705 "inputSchema": {},706 "outputSchema": null,707 "icons": null,708 "annotations": null,709 "meta": null,710 "execution": null711 },712 {713 "name": "template-engine.d.ts",714 "title": null,715 "description": "Script: template-engine.d.ts. Code:\ninterface TemplateVariables {\n title: string;\n date: string;\n datetime: string;\n type: string;\n}\ndeclare function buildTemplateVariables(input?: Partial<TemplateVariables>, now?: Date): TemplateVariables;\ndeclare function renderTemplate(template: string, variables: TemplateVariables): string;\n\nexport { type TemplateVariables, buildTemplateVariables, renderTemplate };\n",716 "inputSchema": {},717 "outputSchema": null,718 "icons": null,719 "annotations": null,720 "meta": null,721 "execution": null722 },723 {724 "name": "session-repair.js",725 "title": null,726 "description": "Script: session-repair.js. Code:\nimport {\n analyzeSession,\n computeParentRelinks,\n extractToolUses,\n findCorruptedEntries,\n parseTranscript,\n repairSession\n} from \"../chunk-L53L5FCL.js\";\nexport {\n analyzeSession,\n computeParentRelinks,\n extractToolUses,\n findCorruptedEntries,\n parseTranscript,\n repairSession\n};\n",727 "inputSchema": {},728 "outputSchema": null,729 "icons": null,730 "annotations": null,731 "meta": null,732 "execution": null733 },734 {735 "name": "config.js",736 "title": null,737 "description": "Script: config.js. Code:\nimport {\n getVaultPath\n} from \"../chunk-4KDZZW4X.js\";\nexport {\n getVaultPath\n};\n",738 "inputSchema": {},739 "outputSchema": null,740 "icons": null,741 "annotations": null,742 "meta": null,743 "execution": null744 },745 {746 "name": "config.d.ts",747 "title": null,748 "description": "Script: config.d.ts. Code:\n/**\n * Get the vault path from CLAWVAULT_PATH env var or throw\n */\ndeclare function getVaultPath(): string;\n\nexport { getVaultPath };\n",749 "inputSchema": {},750 "outputSchema": null,751 "icons": null,752 "annotations": null,753 "meta": null,754 "execution": null755 },756 {757 "name": "auto-linker.d.ts",758 "title": null,759 "description": "Script: auto-linker.d.ts. Code:\nimport { EntityIndex } from './entity-index.js';\n\n/**\n * Auto-link entities in markdown content.\n * Only links first occurrence of each entity.\n * Skips protected ranges (frontmatter, code, existing links, URLs).\n */\ndeclare function autoLink(content: string, index: EntityIndex): string;\n/**\n * Show what would be linked (dry run)\n */\ndeclare function dryRunLink(content: string, index: EntityIndex): Array<{\n alias: string;\n path: string;\n line: number;\n}>;\n/**\n * Find unlinked mentions of entities (suggested links).\n */\ndeclare function findUnlinkedMentions(content: string, index: EntityIndex): Array<{\n alias: string;\n path: string;\n line: number;\n}>;\n\nexport { autoLink, dryRunLink, findUnlinkedMentions };\n",760 "inputSchema": {},761 "outputSchema": null,762 "icons": null,763 "annotations": null,764 "meta": null,765 "execution": null766 },767 {768 "name": "session-utils.d.ts",769 "title": null,770 "description": "Script: session-utils.d.ts. Code:\n/**\n * Session discovery utilities for OpenClaw transcripts\n */\ninterface SessionInfo {\n sessionId: string;\n sessionKey: string;\n agentId: string;\n filePath: string;\n updatedAt?: number;\n}\ninterface SessionsStore {\n [sessionKey: string]: {\n sessionId: string;\n updatedAt?: number;\n [key: string]: unknown;\n };\n}\n/**\n * Get the OpenClaw agents directory\n */\ndeclare function getOpenClawAgentsDir(): string;\n/**\n * Get the sessions directory for an agent\n */\ndeclare function getSessionsDir(agentId: string): string;\n/**\n * Get the path to sessions.json for an agent\n */\ndeclare function getSessionsJsonPath(agentId: string): string;\n/**\n * Get the path to a session JSONL file\n */\ndeclare function getSessionFilePath(agentId: string, sessionId: string): string;\n/**\n * List all available agents\n */\ndeclare function listAgents(): string[];\n/**\n * Load sessions.json for an agent\n */\ndeclare function loadSessionsStore(agentId: string): SessionsStore | null;\n/**\n * Find the current/main session for an agent\n */\ndeclare function findMainSession(agentId: string): SessionInfo | null;\n/**\n * Find a session by ID\n */\ndeclare function findSessionById(agentId: string, sessionId: string): SessionInfo | null;\n/**\n * List all sessions for an agent\n */\ndeclare function listSessions(agentId: string): SessionInfo[];\n/**\n * Create a backup of a session file\n */\ndeclare function backupSession(filePath: string): string;\n\nexport { type SessionInfo, type SessionsStore, backupSession, findMainSession, findSessionById, getOpenClawAgentsDir, getSessionFilePath, getSessionsDir, getSessionsJsonPath, listAgents, listSessions, loadSessionsStore };\n",771 "inputSchema": {},772 "outputSchema": null,773 "icons": null,774 "annotations": null,775 "meta": null,776 "execution": null777 },778 {779 "name": "auto-linker.js",780 "title": null,781 "description": "Script: auto-linker.js. Code:\nimport {\n autoLink,\n dryRunLink,\n findUnlinkedMentions\n} from \"../chunk-42MXU7A6.js\";\nimport \"../chunk-J7ZWCI2C.js\";\nexport {\n autoLink,\n dryRunLink,\n findUnlinkedMentions\n};\n",782 "inputSchema": {},783 "outputSchema": null,784 "icons": null,785 "annotations": null,786 "meta": null,787 "execution": null788 },789 {790 "name": "chunk-7766SIJP.js",791 "title": null,792 "description": "Script: chunk-7766SIJP.js. Code:\n// src/lib/template-engine.ts\nfunction buildTemplateVariables(input = {}, now = /* @__PURE__ */ new Date()) {\n const datetime = input.datetime ?? now.toISOString();\n const date = input.date ?? datetime.split(\"T\")[0];\n return {\n title: input.title ?? \"\",\n type: input.type ?? \"\",\n date,\n datetime\n };\n}\nfunction renderTemplate(template, variables) {\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_-]+)\\s*\\}\\}/g, (match, key) => {\n const value = variables[key];\n return value !== void 0 ? String(value) : match;\n });\n}\n\nexport {\n buildTemplateVariables,\n renderTemplate\n};\n",793 "inputSchema": {},794 "outputSchema": null,795 "icons": null,796 "annotations": null,797 "meta": null,798 "execution": null799 },800 {801 "name": "chunk-MXNXWOPL.js",802 "title": null,803 "description": "Script: chunk-MXNXWOPL.js. Code:\nimport {\n DEFAULT_CATEGORIES,\n QmdUnavailableError,\n SearchEngine,\n TYPE_TO_CATEGORY,\n extractTags,\n extractWikiLinks,\n hasQmd,\n qmdEmbed,\n qmdUpdate\n} from \"./chunk-VJIFT5T5.js\";\n\n// src/lib/vault.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport matter from \"gray-matter\";\nimport { glob } from \"glob\";\nvar CONFIG_FILE = \".clawvault.json\";\nvar INDEX_FILE = \".clawvault-index.json\";\nvar ClawVault = class {\n config;\n search;\n initialized = false;\n constructor(vaultPath) {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n this.config = {\n path: path.resolve(vaultPath),\n name: path.basename(vaultPath),\n categories: DEFAULT_CATEGORIES,\n qmdCollection: void 0,\n qmdRoot: void 0\n };\n this.search = new SearchEngine();\n this.applyQmdConfig();\n }\n /**\n * Initialize a new vault\n */\n async init(options = {}) {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vaultPath = this.config.path;\n this.config = { ...this.config, ...options };\n this.applyQmdConfig();\n if (!fs.existsSync(vaultPath)) {\n fs.mkdirSync(vaultPath, { recursive: true });\n }\n for (const category of this.config.categories) {\n const catPath = path.join(vaultPath, category);\n if (!fs.existsSync(catPath)) {\n fs.mkdirSync(catPath, { recursive: true });\n }\n }\n await this.createTemplates();\n const readmePath = path.join(vaultPath, \"README.md\");\n if (!fs.existsSync(readmePath)) {\n fs.writeFileSync(readmePath, this.generateReadme());\n }\n const configPath = path.join(vaultPath, CONFIG_FILE);\n const meta = {\n name: this.config.name,\n version: \"1.0.0\",\n created: (/* @__PURE__ */ new Date()).toISOString(),\n lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),\n categories: this.config.categories,\n documentCount: 0,\n qmdCollection: this.getQmdCollection(),\n qmdRoot: this.getQmdRoot()\n };\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n this.initialized = true;\n }\n /**\n * Load an existing vault\n */\n async load() {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vaultPath = this.config.path;\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (!fs.existsSync(configPath)) {\n throw new Error(`Not a ClawVault: ${vaultPath} (missing ${CONFIG_FILE})`);\n }\n const meta = JSON.parse(fs.readFileSync(configPath, \"utf-8\"));\n this.config.name = meta.name;\n this.config.categories = meta.categories;\n this.config.qmdCollection = meta.qmdCollection;\n this.config.qmdRoot = meta.qmdRoot;\n if (!meta.qmdCollection || !meta.qmdRoot) {\n meta.qmdCollection = meta.qmdCollection || meta.name;\n meta.qmdRoot = meta.qmdRoot || this.config.path;\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n }\n this.applyQmdConfig(meta);\n await this.reindex();\n this.initialized = true;\n }\n /**\n * Reindex all documents\n */\n async reindex() {\n this.search.clear();\n const files = await glob(\"**/*.md\", {\n cwd: this.config.path,\n ignore: [\"**/node_modules/**\", \"**/.*\"]\n });\n for (const file of files) {\n const doc = await this.loadDocument(file);\n if (doc) {\n this.search.addDocument(doc);\n }\n }\n await this.saveIndex();\n return this.search.size;\n }\n /**\n * Load a document from disk\n */\n async loadDocument(relativePath) {\n try {\n const fullPath = path.join(this.config.path, relativePath);\n const content = fs.readFileSync(fullPath, \"utf-8\");\n const { data: frontmatter, content: body } = matter(content);\n const stats = fs.statSync(fullPath);\n const parts = relativePath.split(path.sep);\n const category = parts.length > 1 ? parts[0] : \"root\";\n const filename = path.basename(relativePath, \".md\");\n return {\n id: relativePath.replace(/\\.md$/, \"\"),\n path: fullPath,\n category,\n title: frontmatter.title || filename,\n content: body,\n frontmatter,\n links: extractWikiLinks(body),\n tags: extractTags(body),\n modified: stats.mtime\n };\n } catch (err) {\n console.error(`Error loading ${relativePath}:`, err);\n return null;\n }\n }\n /**\n * Store a new document\n */\n async store(options) {\n const {\n category,\n title,\n content,\n frontmatter = {},\n overwrite = false,\n qmdUpdate: triggerUpdate = false,\n qmdEmbed: triggerEmbed = false\n } = options;\n const filename = this.slugify(title) + \".md\";\n const relativePath = path.join(category, filename);\n const fullPath = path.join(this.config.path, relativePath);\n if (fs.existsSync(fullPath) && !overwrite) {\n throw new Error(`Document already exists: ${relativePath}. Use overwrite: true to replace.`);\n }\n const categoryPath = path.join(this.config.path, category);\n if (!fs.existsSync(categoryPath)) {\n fs.mkdirSync(categoryPath, { recursive: true });\n }\n const fm = {\n title,\n date: (/* @__PURE__ */ new Date()).toISOString().split(\"T\")[0],\n ...frontmatter\n };\n const fileContent = matter.stringify(content, fm);\n fs.writeFileSync(fullPath, fileContent);\n const doc = await this.loadDocument(relativePath);\n if (doc) {\n this.search.addDocument(doc);\n await this.saveIndex();\n }\n if (triggerUpdate || triggerEmbed) {\n qmdUpdate(this.getQmdCollection());\n if (triggerEmbed) {\n qmdEmbed(this.getQmdCollection());\n }\n }\n return doc;\n }\n /**\n * Quick store to inbox\n */\n async capture(note, title) {\n const autoTitle = title || `note-${Date.now()}`;\n return this.store({\n category: \"inbox\",\n title: autoTitle,\n content: note\n });\n }\n /**\n * Search the vault (BM25 via qmd)\n */\n async find(query, options = {}) {\n return this.search.search(query, options);\n }\n /**\n * Semantic/vector search (via qmd vsearch)\n */\n async vsearch(query, options = {}) {\n return this.search.vsearch(query, options);\n }\n /**\n * Combined search with query expansion (via qmd query)\n */\n async query(query, options = {}) {\n return this.search.query(query, options);\n }\n /**\n * Get a document by ID or path\n */\n async get(idOrPath) {\n const normalized = idOrPath.replace(/\\.md$/, \"\");\n const docs = this.search.getAllDocuments();\n return docs.find((d) => d.id === normalized) || null;\n }\n /**\n * List documents in a category\n */\n async list(category) {\n const docs = this.search.getAllDocuments();\n if (category) {\n return docs.filter((d) => d.category === category);\n }\n return docs;\n }\n /**\n * Sync vault to another location (for Obsidian on Windows, etc.)\n */\n async sync(options) {\n const { target, deleteOrphans = false, dryRun = false } = options;\n const result = {\n copied: [],\n deleted: [],\n unchanged: [],\n errors: []\n };\n const sourceFiles = await glob(\"**/*.md\", {\n cwd: this.config.path,\n ignore: [\"**/node_modules/**\"]\n });\n if (!dryRun && !fs.existsSync(target)) {\n fs.mkdirSync(target, { recursive: true });\n }\n for (const file of sourceFiles) {\n const sourcePath = path.join(this.config.path, file);\n const targetPath = path.join(target, file);\n try {\n const sourceStats = fs.statSync(sourcePath);\n let shouldCopy = true;\n if (fs.existsSync(targetPath)) {\n const targetStats = fs.statSync(targetPath);\n if (sourceStats.mtime <= targetStats.mtime) {\n result.unchanged.push(file);\n shouldCopy = false;\n }\n }\n if (shouldCopy) {\n if (!dryRun) {\n const targetDir = path.dirname(targetPath);\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n fs.copyFileSync(sourcePath, targetPath);\n }\n result.copied.push(file);\n }\n } catch (err) {\n result.errors.push(`${file}: ${err}`);\n }\n }\n if (deleteOrphans) {\n const targetFiles = await glob(\"**/*.md\", { cwd: target });\n const sourceSet = new Set(sourceFiles);\n for (const file of targetFiles) {\n if (!sourceSet.has(file)) {\n if (!dryRun) {\n fs.unlinkSync(path.join(target, file));\n }\n result.deleted.push(file);\n }\n }\n }\n return result;\n }\n /**\n * Get vault statistics\n */\n async stats() {\n const docs = this.search.getAllDocuments();\n const categories = {};\n const allTags = /* @__PURE__ */ new Set();\n let totalLinks = 0;\n for (const doc of docs) {\n categories[doc.category] = (categories[doc.category] || 0) + 1;\n totalLinks += doc.links.length;\n doc.tags.forEach((t) => allTags.add(t));\n }\n return {\n documents: docs.length,\n categories,\n links: totalLinks,\n tags: [...allTags].sort()\n };\n }\n /**\n * Get all categories\n */\n getCategories() {\n return this.config.categories;\n }\n /**\n * Check if vault is initialized\n */\n isInitialized() {\n return this.initialized;\n }\n /**\n * Get vault path\n */\n getPath() {\n return this.config.path;\n }\n /**\n * Get vault name\n */\n getName() {\n return this.config.name;\n }\n /**\n * Get qmd collection name\n */\n getQmdCollection() {\n return this.config.qmdCollection || this.config.name;\n }\n /**\n * Get qmd collection root\n */\n getQmdRoot() {\n return this.config.qmdRoot || this.config.path;\n }\n // === Memory Type System ===\n /**\n * Store a memory with type classification\n * Automatically routes to correct category based on type\n */\n async remember(type, title, content, frontmatter = {}) {\n const category = TYPE_TO_CATEGORY[type];\n return this.store({\n category,\n title,\n content,\n frontmatter: { ...frontmatter, memoryType: type }\n });\n }\n // === Handoff System ===\n /**\n * Create a session handoff document\n * Call this before context death or long pauses\n */\n async createHandoff(handoff) {\n const now = /* @__PURE__ */ new Date();\n const dateStr = now.toISOString().split(\"T\")[0];\n const timeStr = now.toISOString().split(\"T\")[1].slice(0, 5).replace(\":\", \"\");\n const fullHandoff = {\n ...handoff,\n created: now.toISOString()\n };\n const content = this.formatHandoff(fullHandoff);\n const frontmatter = {\n type: \"handoff\",\n workingOn: handoff.workingOn,\n blocked: handoff.blocked,\n nextSteps: handoff.nextSteps\n };\n if (handoff.sessionKey) frontmatter.sessionKey = handoff.sessionKey;\n if (handoff.feeling) frontmatter.feeling = handoff.feeling;\n if (handoff.decisions) frontmatter.decisions = handoff.decisions;\n if (handoff.openQuestions) frontmatter.openQuestions = handoff.openQuestions;\n return this.store({\n category: \"handoffs\",\n title: `handoff-${dateStr}-${timeStr}`,\n content,\n frontmatter\n });\n }\n /**\n * Format handoff as readable markdown\n */\n formatHandoff(h) {\n let md = `# Session Handoff\n\n`;\n md += `**Created:** ${h.created}\n`;\n if (h.sessionKey) md += `**Session:** ${h.sessionKey}\n`;\n if (h.feeling) md += `**Feeling:** ${h.feeling}\n`;\n md += `\n`;\n md += `## Working On\n`;\n h.workingOn.forEach((w) => md += `- ${w}\n`);\n md += `\n`;\n md += `## Blocked\n`;\n if (h.blocked.length === 0) md += `- Nothing currently blocked\n`;\n else h.blocked.forEach((b) => md += `- ${b}\n`);\n md += `\n`;\n md += `## Next Steps\n`;\n h.nextSteps.forEach((n) => md += `- ${n}\n`);\n if (h.decisions && h.decisions.length > 0) {\n md += `\n## Decisions Made\n`;\n h.decisions.forEach((d) => md += `- ${d}\n`);\n }\n if (h.openQuestions && h.openQuestions.length > 0) {\n md += `\n## Open Questions\n`;\n h.openQuestions.forEach((q) => md += `- ${q}\n`);\n }\n return md;\n }\n // === Session Recap (Bootstrap Hook) ===\n /**\n * Generate a session recap - who I was\n * Call this on bootstrap to restore context\n */\n async generateRecap(options = {}) {\n const { handoffLimit = 3, brief = false } = options;\n const handoffDocs = await this.list(\"handoffs\");\n const recentHandoffs = handoffDocs.sort((a, b) => b.modified.getTime() - a.modified.getTime()).slice(0, handoffLimit).map((doc) => this.parseHandoff(doc));\n const projectDocs = await this.list(\"projects\");\n const activeProjects = projectDocs.filter((d) => d.frontmatter.status !== \"completed\" && d.frontmatter.status !== \"archived\").map((d) => d.title);\n const commitmentDocs = await this.list(\"commitments\");\n const pendingCommitments = commitmentDocs.filter((d) => d.frontmatter.status !== \"done\").map((d) => d.title);\n const decisionDocs = await this.list(\"decisions\");\n const recentDecisions = decisionDocs.sort((a, b) => b.modified.getTime() - a.modified.getTime()).slice(0, brief ? 3 : 5).map((d) => d.title);\n const lessonDocs = await this.list(\"lessons\");\n const recentLessons = lessonDocs.sort((a, b) => b.modified.getTime() - a.modified.getTime()).slice(0, brief ? 3 : 5).map((d) => d.title);\n let keyRelationships = [];\n if (!brief) {\n const peopleDocs = await this.list(\"people\");\n keyRelationships = peopleDocs.filter((d) => d.frontmatter.importance === \"high\" || d.frontmatter.role).map((d) => `${d.title}${d.frontmatter.role ? ` (${d.frontmatter.role})` : \"\"}`);\n }\n const feelings = recentHandoffs.map((h) => h.feeling).filter(Boolean);\n const emotionalArc = feelings.length > 0 ? feelings.join(\" \\u2192 \") : void 0;\n return {\n generated: (/* @__PURE__ */ new Date()).toISOString(),\n recentHandoffs,\n activeProjects,\n pendingCommitments,\n recentDecisions,\n recentLessons,\n keyRelationships,\n emotionalArc\n };\n }\n /**\n * Format recap as readable markdown for injection\n */\n formatRecap(recap, options = {}) {\n const { brief = false } = options;\n let md = `# Who I Was\n\n`;\n md += `*Generated: ${recap.generated}*\n\n`;\n if (recap.emotionalArc) {\n md += `**Emotional arc:** ${recap.emotionalArc}\n\n`;\n }\n if (recap.recentHandoffs.length > 0) {\n md += `## Recent Sessions\n`;\n for (const h of recap.recentHandoffs) {\n if (brief) {\n md += `- **${h.created.split(\"T\")[0]}:** ${h.workingOn.slice(0, 2).join(\", \")}`;\n if (h.nextSteps.length > 0) md += ` \\u2192 ${h.nextSteps[0]}`;\n md += `\n`;\n } else {\n md += `\n### ${h.created.split(\"T\")[0]}\n`;\n md += `**Working on:** ${h.workingOn.join(\", \")}\n`;\n if (h.blocked.length > 0) md += `**Blocked:** ${h.blocked.join(\", \")}\n`;\n md += `**Next:** ${h.nextSteps.join(\", \")}\n`;\n }\n }\n md += `\n`;\n }\n if (recap.activeProjects.length > 0) {\n md += `## Active Projects\n`;\n recap.activeProjects.forEach((p) => md += `- ${p}\n`);\n md += `\n`;\n }\n if (recap.pendingCommitments.length > 0) {\n md += `## Pending Commitments\n`;\n recap.pendingCommitments.forEach((c) => md += `- ${c}\n`);\n md += `\n`;\n }\n if (recap.recentDecisions && recap.recentDecisions.length > 0) {\n md += `## Recent Decisions\n`;\n recap.recentDecisions.forEach((d) => md += `- ${d}\n`);\n md += `\n`;\n }\n if (recap.recentLessons.length > 0) {\n md += `## Recent Lessons\n`;\n recap.recentLessons.forEach((l) => md += `- ${l}\n`);\n md += `\n`;\n }\n if (!brief && recap.keyRelationships.length > 0) {\n md += `## Key People\n`;\n recap.keyRelationships.forEach((r) => md += `- ${r}\n`);\n }\n return md;\n }\n /**\n * Parse a handoff document back into structured form\n */\n parseHandoff(doc) {\n return {\n created: doc.frontmatter.date || doc.modified.toISOString(),\n sessionKey: doc.frontmatter.sessionKey,\n workingOn: doc.frontmatter.workingOn || [],\n blocked: doc.frontmatter.blocked || [],\n nextSteps: doc.frontmatter.nextSteps || [],\n decisions: doc.frontmatter.decisions,\n openQuestions: doc.frontmatter.openQuestions,\n feeling: doc.frontmatter.feeling\n };\n }\n // === Private helpers ===\n applyQmdConfig(meta) {\n const collection = meta?.qmdCollection || this.config.qmdCollection || this.config.name;\n const root = meta?.qmdRoot || this.config.qmdRoot || this.config.path;\n this.config.qmdCollection = collection;\n this.config.qmdRoot = root;\n this.search.setVaultPath(this.config.path);\n this.search.setCollection(collection);\n this.search.setCollectionRoot(root);\n }\n slugify(text) {\n return text.toLowerCase().replace(/[^\\w\\s-]/g, \"\").replace(/\\s+/g, \"-\").replace(/-+/g, \"-\").trim();\n }\n async saveIndex() {\n const indexPath = path.join(this.config.path, INDEX_FILE);\n const data = this.search.export();\n fs.writeFileSync(indexPath, JSON.stringify(data, null, 2));\n const configPath = path.join(this.config.path, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n const meta = JSON.parse(fs.readFileSync(configPath, \"utf-8\"));\n meta.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();\n meta.documentCount = this.search.size;\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n }\n }\n async createTemplates() {\n const templatesPath = path.join(this.config.path, \"templates\");\n if (!fs.existsSync(templatesPath)) {\n fs.mkdirSync(templatesPath, { recursive: true });\n }\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(moduleDir, \"../templates\"),\n path.resolve(moduleDir, \"../../templates\")\n ];\n const builtinDir = candidates.find((dir) => fs.existsSync(dir) && fs.statSync(dir).isDirectory());\n if (!builtinDir) return;\n for (const entry of fs.readdirSync(builtinDir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue;\n if (entry.name === \"daily.md\") continue;\n const sourcePath = path.join(builtinDir, entry.name);\n const targetPath = path.join(templatesPath, entry.name);\n if (!fs.existsSync(targetPath)) {\n fs.copyFileSync(sourcePath, targetPath);\n }\n }\n }\n generateReadme() {\n return `# ${this.config.name} \\u{1F418}\n\nAn elephant never forgets.\n\n## Structure\n\n${this.config.categories.map((c) => `- \\`/${c}/\\` \\u2014 ${this.getCategoryDescription(c)}`).join(\"\\n\")}\n\n## Quick Search\n\n\\`\\`\\`bash\nclawvault search \"query\"\n\\`\\`\\`\n\n## Quick Capture\n\n\\`\\`\\`bash\nclawvault store --category inbox --title \"note\" --content \"...\"\n\\`\\`\\`\n\n---\n\n*Managed by [ClawVault](https://github.com/Versatly/clawvault)*\n`;\n }\n getCategoryDescription(category) {\n const descriptions = {\n // Memory type categories (Benthic's taxonomy)\n facts: \"Raw information, data points, things that are true\",\n feelings: \"Emotional states, reactions, energy levels\",\n decisions: \"Choices made with context and reasoning\",\n lessons: \"What I learned, insights, patterns observed\",\n commitments: \"Promises, goals, obligations to fulfill\",\n preferences: \"Likes, dislikes, how I want things\",\n people: \"Relationships, one file per person\",\n projects: \"Active work, ventures, ongoing efforts\",\n // System categories\n handoffs: \"Session bridges \\u2014 what I was doing, what comes next\",\n transcripts: \"Session summaries and logs\",\n goals: \"Long-term and short-term objectives\",\n patterns: \"Recurring behaviors (\\u2192 lessons)\",\n inbox: \"Quick capture \\u2192 process later\",\n templates: \"Templates for each document type\"\n };\n return descriptions[category] || category;\n }\n};\nasync function findVault(startPath = process.cwd()) {\n let current = path.resolve(startPath);\n while (current !== path.dirname(current)) {\n const configPath = path.join(current, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n const vault = new ClawVault(current);\n await vault.load();\n return vault;\n }\n current = path.dirname(current);\n }\n return null;\n}\nasync function createVault(vaultPath, options = {}) {\n const vault = new ClawVault(vaultPath);\n await vault.init(options);\n return vault;\n}\n\nexport {\n ClawVault,\n findVault,\n createVault\n};\n",804 "inputSchema": {},805 "outputSchema": null,806 "icons": null,807 "annotations": null,808 "meta": null,809 "execution": null810 },811 {812 "name": "chunk-QYJI73KF.js",813 "title": null,814 "description": "Script: chunk-QYJI73KF.js. Code:\nimport {\n DEFAULT_CATEGORIES,\n hasQmd\n} from \"./chunk-VJIFT5T5.js\";\n\n// src/commands/setup.ts\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport { execFileSync } from \"child_process\";\nvar CONFIG_FILE = \".clawvault.json\";\nfunction resolveVaultTarget() {\n const envPath = process.env.CLAWVAULT_PATH?.trim();\n const home = os.homedir();\n if (envPath) {\n const vaultPath = path.resolve(envPath);\n return { vaultPath, source: \"CLAWVAULT_PATH\", existed: fs.existsSync(vaultPath) };\n }\n const candidates = [\n { vaultPath: path.join(home, \".openclaw\", \"workspace\", \"memory\"), source: \"OpenClaw default\" },\n { vaultPath: path.resolve(process.cwd(), \"memory\"), source: \"./memory\" },\n { vaultPath: path.join(home, \"memory\"), source: \"~/memory\" }\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(candidate.vaultPath)) {\n return { ...candidate, existed: true };\n }\n }\n const fallback = candidates[0];\n return { ...fallback, existed: false };\n}\nfunction ensureVaultStructure(vaultPath) {\n fs.mkdirSync(vaultPath, { recursive: true });\n for (const category of DEFAULT_CATEGORIES) {\n fs.mkdirSync(path.join(vaultPath, category), { recursive: true });\n }\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (fs.existsSync(configPath)) return false;\n const now = (/* @__PURE__ */ new Date()).toISOString();\n const name = path.basename(vaultPath);\n const meta = {\n name,\n version: \"1.0.0\",\n created: now,\n lastUpdated: now,\n categories: DEFAULT_CATEGORIES,\n documentCount: 0,\n qmdCollection: name,\n qmdRoot: vaultPath\n };\n fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));\n return true;\n}\nfunction getQmdConfig(vaultPath) {\n const configPath = path.join(vaultPath, CONFIG_FILE);\n if (fs.existsSync(configPath)) {\n try {\n const meta = JSON.parse(fs.readFileSync(configPath, \"utf-8\"));\n return {\n collection: meta.qmdCollection || meta.name || path.basename(vaultPath),\n root: meta.qmdRoot || vaultPath\n };\n } catch {\n return { collection: path.basename(vaultPath), root: vaultPath };\n }\n }\n return { collection: path.basename(vaultPath), root: vaultPath };\n}\nasync function setupCommand() {\n const target = resolveVaultTarget();\n if (target.existed && !fs.statSync(target.vaultPath).isDirectory()) {\n throw new Error(`Vault path is not a directory: ${target.vaultPath}`);\n }\n if (!target.existed) fs.mkdirSync(target.vaultPath, { recursive: true });\n console.log(`${target.existed ? \"Found\" : \"Created\"} vault path (${target.source}): ${target.vaultPath}`);\n const initialized = ensureVaultStructure(target.vaultPath);\n console.log(initialized ? \"Initialized vault structure.\" : \"Vault structure already present.\");\n console.log(\"\\nTip: add this to your shell config:\");\n console.log(` export CLAWVAULT_PATH=\"${target.vaultPath}\"`);\n if (hasQmd()) {\n const { collection, root } = getQmdConfig(target.vaultPath);\n try {\n execFileSync(\"qmd\", [\"collection\", \"add\", root, \"--name\", collection, \"--mask\", \"**/*.md\"], {\n stdio: \"ignore\"\n });\n console.log(`qmd collection ready: ${collection}`);\n } catch {\n console.log(\"qmd collection already exists or could not be created.\");\n }\n } else {\n console.log(\"qmd not found; skipping collection setup.\");\n }\n}\n\nexport {\n setupCommand\n};\n",815 "inputSchema": {},816 "outputSchema": null,817 "icons": null,818 "annotations": null,819 "meta": null,820 "execution": null821 },822 {823 "name": "chunk-42MXU7A6.js",824 "title": null,825 "description": "Script: chunk-42MXU7A6.js. Code:\nimport {\n getSortedAliases\n} from \"./chunk-J7ZWCI2C.js\";\n\n// src/lib/auto-linker.ts\nfunction findProtectedRanges(content) {\n const ranges = [];\n const fmMatch = content.match(/^---\\n[\\s\\S]*?\\n---/);\n if (fmMatch) {\n ranges.push({ start: 0, end: fmMatch[0].length });\n }\n const codeBlockRegex = /```[\\s\\S]*?```|~~~[\\s\\S]*?~~~/g;\n let match;\n while ((match = codeBlockRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n const inlineCodeRegex = /`[^`]+`/g;\n while ((match = inlineCodeRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n const wikiLinkRegex = /\\[\\[[^\\]]+\\]\\]/g;\n while ((match = wikiLinkRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n const urlRegex = /https?:\\/\\/[^\\s)>\\]]+/g;\n while ((match = urlRegex.exec(content)) !== null) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n return ranges;\n}\nfunction isProtected(pos, ranges) {\n return ranges.some((r) => pos >= r.start && pos < r.end);\n}\nfunction createLineLookup(content) {\n const lines = content.split(\"\\n\");\n let charPos = 0;\n const lineStarts = [];\n for (const line of lines) {\n lineStarts.push(charPos);\n charPos += line.length + 1;\n }\n return (pos) => {\n for (let i = lineStarts.length - 1; i >= 0; i--) {\n if (pos >= lineStarts[i]) return i + 1;\n }\n return 1;\n };\n}\nfunction autoLink(content, index) {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const linkedEntities = /* @__PURE__ */ new Set();\n let result = content;\n let offset = 0;\n for (const { alias, path } of sortedAliases) {\n if (linkedEntities.has(path)) continue;\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, \"gi\");\n let match;\n while ((match = regex.exec(content)) !== null) {\n const originalPos = match.index;\n const adjustedPos = originalPos + offset;\n if (isProtected(originalPos, protectedRanges)) continue;\n const beforeMatch = result.substring(0, adjustedPos);\n const openBrackets = (beforeMatch.match(/\\[\\[/g) || []).length;\n const closeBrackets = (beforeMatch.match(/\\]\\]/g) || []).length;\n if (openBrackets > closeBrackets) continue;\n const originalText = match[0];\n const replacement = originalText.toLowerCase() === path.split(\"/\").pop()?.toLowerCase() ? `[[${path}]]` : `[[${path}|${originalText}]]`;\n result = result.substring(0, adjustedPos) + replacement + result.substring(adjustedPos + originalText.length);\n offset += replacement.length - originalText.length;\n linkedEntities.add(path);\n break;\n }\n }\n return result;\n}\nfunction dryRunLink(content, index) {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const linkedEntities = /* @__PURE__ */ new Set();\n const matches = [];\n const getLineNumber = createLineLookup(content);\n for (const { alias, path } of sortedAliases) {\n if (linkedEntities.has(path)) continue;\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, \"gi\");\n let match;\n while ((match = regex.exec(content)) !== null) {\n if (isProtected(match.index, protectedRanges)) continue;\n matches.push({\n alias: match[0],\n path,\n line: getLineNumber(match.index)\n });\n linkedEntities.add(path);\n break;\n }\n }\n return matches;\n}\nfunction findUnlinkedMentions(content, index) {\n const protectedRanges = findProtectedRanges(content);\n const sortedAliases = getSortedAliases(index);\n const matches = [];\n const seen = /* @__PURE__ */ new Set();\n const getLineNumber = createLineLookup(content);\n for (const { alias, path } of sortedAliases) {\n if (seen.has(path)) continue;\n const escapedAlias = alias.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`\\\\b${escapedAlias}\\\\b`, \"gi\");\n let match;\n while ((match = regex.exec(content)) !== null) {\n if (isProtected(match.index, protectedRanges)) continue;\n matches.push({\n alias: match[0],\n path,\n line: getLineNumber(match.index)\n });\n seen.add(path);\n break;\n }\n }\n return matches;\n}\n\nexport {\n autoLink,\n dryRunLink,\n findUnlinkedMentions\n};\n",826 "inputSchema": {},827 "outputSchema": null,828 "icons": null,829 "annotations": null,830 "meta": null,831 "execution": null832 },833 {834 "name": "chunk-MZZJLQNQ.js",835 "title": null,836 "description": "Script: chunk-MZZJLQNQ.js. Code:\n// src/commands/checkpoint.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { execFileSync } from \"child_process\";\nvar CLAWVAULT_DIR = \".clawvault\";\nvar CHECKPOINT_FILE = \"last-checkpoint.json\";\nvar SESSION_STATE_FILE = \"session-state.json\";\nvar DIRTY_DEATH_FLAG = \"dirty-death.flag\";\nvar pendingCheckpoint = null;\nvar pendingData = null;\nfunction ensureClawvaultDir(vaultPath) {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\nfunction writeCheckpointToDisk(dir, data) {\n const checkpointPath = path.join(dir, CHECKPOINT_FILE);\n fs.writeFileSync(checkpointPath, JSON.stringify(data, null, 2));\n const flagPath = path.join(dir, DIRTY_DEATH_FLAG);\n fs.writeFileSync(flagPath, data.timestamp);\n}\nfunction parseTokenEstimate(raw) {\n if (!raw) return void 0;\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : void 0;\n}\nfunction loadSessionState(dir) {\n const sessionStatePath = path.join(dir, SESSION_STATE_FILE);\n if (!fs.existsSync(sessionStatePath)) return null;\n try {\n return JSON.parse(fs.readFileSync(sessionStatePath, \"utf-8\"));\n } catch {\n return null;\n }\n}\nfunction getEnvSessionState() {\n return {\n sessionKey: process.env.OPENCLAW_SESSION_KEY,\n model: process.env.OPENCLAW_MODEL,\n tokenEstimate: parseTokenEstimate(\n process.env.OPENCLAW_TOKEN_ESTIMATE || process.env.OPENCLAW_CONTEXT_TOKENS\n )\n };\n}\nfunction triggerUrgentWake(data) {\n const summary = [\n data.workingOn ? `Working on: ${data.workingOn}` : null,\n data.focus ? `Focus: ${data.focus}` : null,\n data.blocked ? `Blocked: ${data.blocked}` : null\n ].filter(Boolean).join(\" | \");\n const text = summary ? `Urgent checkpoint saved. ${summary}` : \"Urgent checkpoint saved.\";\n try {\n execFileSync(\"openclaw\", [\"gateway\", \"wake\", \"--text\", text, \"--mode\", \"now\"], {\n stdio: \"inherit\"\n });\n } catch (err) {\n if (err?.code === \"ENOENT\") {\n throw new Error(\"Urgent wake failed: openclaw CLI not found.\");\n }\n throw new Error(`Urgent wake failed: ${err?.message || \"unknown error\"}`);\n }\n}\nasync function flush() {\n if (pendingCheckpoint) {\n clearTimeout(pendingCheckpoint);\n pendingCheckpoint = null;\n }\n if (!pendingData) return null;\n const { dir, data } = pendingData;\n pendingData = null;\n writeCheckpointToDisk(dir, data);\n return data;\n}\nasync function checkpoint(options) {\n const dir = ensureClawvaultDir(options.vaultPath);\n const data = {\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n workingOn: options.workingOn || null,\n focus: options.focus || null,\n blocked: options.blocked || null,\n urgent: options.urgent || false\n };\n const sessionState = loadSessionState(dir);\n const envState = getEnvSessionState();\n data.sessionId = sessionState?.sessionId;\n data.sessionKey = envState.sessionKey || sessionState?.sessionKey || sessionState?.sessionId;\n data.model = envState.model || sessionState?.model;\n data.tokenEstimate = envState.tokenEstimate ?? sessionState?.tokenEstimate;\n data.sessionStartedAt = sessionState?.startedAt;\n if (options.urgent) {\n if (pendingCheckpoint) {\n clearTimeout(pendingCheckpoint);\n pendingCheckpoint = null;\n }\n pendingData = null;\n writeCheckpointToDisk(dir, data);\n triggerUrgentWake(data);\n } else {\n pendingData = { dir, data };\n if (pendingCheckpoint) clearTimeout(pendingCheckpoint);\n pendingCheckpoint = setTimeout(() => {\n void flush();\n }, 1e3);\n }\n return data;\n}\nasync function clearDirtyFlag(vaultPath) {\n const flagPath = path.join(vaultPath, CLAWVAULT_DIR, DIRTY_DEATH_FLAG);\n if (fs.existsSync(flagPath)) {\n fs.unlinkSync(flagPath);\n }\n}\nasync function cleanExit(vaultPath) {\n await clearDirtyFlag(vaultPath);\n}\nasync function checkDirtyDeath(vaultPath) {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n const flagPath = path.join(dir, DIRTY_DEATH_FLAG);\n const checkpointPath = path.join(dir, CHECKPOINT_FILE);\n if (!fs.existsSync(flagPath)) {\n return { died: false, checkpoint: null, deathTime: null };\n }\n const deathTime = fs.readFileSync(flagPath, \"utf-8\").trim();\n let checkpoint2 = null;\n if (fs.existsSync(checkpointPath)) {\n try {\n checkpoint2 = JSON.parse(fs.readFileSync(checkpointPath, \"utf-8\"));\n } catch {\n }\n }\n return { died: true, checkpoint: checkpoint2, deathTime };\n}\nasync function setSessionState(vaultPath, session) {\n const dir = ensureClawvaultDir(vaultPath);\n const sessionStatePath = path.join(dir, SESSION_STATE_FILE);\n const state = typeof session === \"string\" ? { sessionId: session } : { ...session };\n if (!state.startedAt) {\n state.startedAt = (/* @__PURE__ */ new Date()).toISOString();\n }\n fs.writeFileSync(sessionStatePath, JSON.stringify(state, null, 2));\n}\n\nexport {\n flush,\n checkpoint,\n clearDirtyFlag,\n cleanExit,\n checkDirtyDeath,\n setSessionState\n};\n",837 "inputSchema": {},838 "outputSchema": null,839 "icons": null,840 "annotations": null,841 "meta": null,842 "execution": null843 },844 {845 "name": "link.js",846 "title": null,847 "description": "Script: link.js. Code:\nimport {\n autoLink,\n dryRunLink,\n findUnlinkedMentions\n} from \"../chunk-42MXU7A6.js\";\nimport {\n readBacklinksIndex,\n rebuildBacklinksIndex,\n scanVaultLinks\n} from \"../chunk-4VQTUVH7.js\";\nimport {\n getVaultPath\n} from \"../chunk-4KDZZW4X.js\";\nimport {\n buildEntityIndex\n} from \"../chunk-J7ZWCI2C.js\";\n\n// src/commands/link.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nasync function linkCommand(file, options) {\n const vaultPath = getVaultPath();\n const index = buildEntityIndex(vaultPath);\n const suggestionIndex = filterIndex(index, /* @__PURE__ */ new Set([\"people\", \"projects\", \"decisions\"]));\n const modeCount = [options.backlinks ? 1 : 0, options.orphans ? 1 : 0, options.rebuild ? 1 : 0].reduce((sum, value) => sum + value, 0);\n if (modeCount > 1) {\n console.error(\"Error: Use only one of --backlinks, --orphans, or --rebuild\");\n process.exit(1);\n }\n if (options.rebuild) {\n const result = rebuildBacklinksIndex(vaultPath, { entityIndex: index });\n const orphanSuffix = result.orphans.length > 0 ? `, ${result.orphans.length} orphan(s)` : \"\";\n console.log(`\\u2713 Rebuilt backlinks (${result.backlinks.size} targets, ${result.linkCount} links${orphanSuffix})`);\n return;\n }\n if (options.backlinks) {\n if (file) {\n console.error(\"Error: Use --backlinks without a file argument\");\n process.exit(1);\n }\n const target = resolveBacklinkTarget(options.backlinks, vaultPath, index);\n if (!target) {\n console.error(\"Error: Invalid target for --backlinks\");\n process.exit(1);\n }\n const backlinks = readBacklinksIndex(vaultPath) ?? rebuildBacklinksIndex(vaultPath, { entityIndex: index }).backlinks;\n const sources = backlinks.get(target) || [];\n if (sources.length === 0) {\n console.log(`No backlinks found for ${target}`);\n return;\n }\n console.log(`Backlinks \\u2192 ${target}`);\n for (const source of sources.sort()) {\n console.log(` - ${source}`);\n }\n return;\n }\n if (options.orphans) {\n if (file || options.all) {\n console.error(\"Error: --orphans does not accept a file or --all\");\n process.exit(1);\n }\n const result = scanVaultLinks(vaultPath, { entityIndex: index });\n if (result.orphans.length === 0) {\n console.log(\"\\u2713 No orphan links found\");\n return;\n }\n const orphans = result.orphans.slice().sort((a, b) => a.target.localeCompare(b.target) || a.source.localeCompare(b.source));\n console.log(`\\u26A0 ${orphans.length} orphan link(s) found`);\n for (const orphan of orphans) {\n console.log(` - ${orphan.source} \\u2192 [[${orphan.target}]]`);\n }\n return;\n }\n if (options.all) {\n await linkAllFiles(vaultPath, index, suggestionIndex, options.dryRun);\n return;\n }\n if (!file) {\n console.error(\"Error: Specify a file or use --all\");\n process.exit(1);\n }\n const filePath = path.isAbsolute(file) ? file : path.join(process.cwd(), file);\n if (!fs.existsSync(filePath)) {\n console.error(`Error: File not found: ${filePath}`);\n process.exit(1);\n }\n await linkFile(filePath, index, suggestionIndex, options.dryRun);\n}\nfunction filterIndex(index, categories) {\n const entries = /* @__PURE__ */ new Map();\n const byPath = /* @__PURE__ */ new Map();\n for (const [alias, targetPath] of index.entries) {\n const category = targetPath.split(\"/\")[0];\n if (categories.has(category)) {\n entries.set(alias, targetPath);\n }\n }\n for (const [targetPath, entry] of index.byPath) {\n const category = targetPath.split(\"/\")[0];\n if (categories.has(category)) {\n byPath.set(targetPath, entry);\n }\n }\n return { entries, byPath };\n}\nfunction resolveBacklinkTarget(input, vaultPath, index) {\n let target = input.trim();\n if (!target) return null;\n if (target.startsWith(\"[[\") && target.endsWith(\"]]\")) {\n target = target.slice(2, -2);\n }\n const pipeIndex = target.indexOf(\"|\");\n if (pipeIndex !== -1) {\n target = target.slice(0, pipeIndex);\n }\n const hashIndex = target.indexOf(\"#\");\n if (hashIndex !== -1) {\n target = target.slice(0, hashIndex);\n }\n target = target.trim();\n if (!target) return null;\n if (target.endsWith(\".md\")) {\n target = target.slice(0, -3);\n }\n if (target.startsWith(\"/\")) {\n target = target.slice(1);\n }\n const candidate = path.isAbsolute(target) ? target : path.join(vaultPath, target);\n const withExtension = candidate.endsWith(\".md\") ? candidate : `${candidate}.md`;\n if (fs.existsSync(candidate) && candidate.endsWith(\".md\")) {\n return toVaultId(vaultPath, candidate);\n }\n if (fs.existsSync(withExtension)) {\n return toVaultId(vaultPath, withExtension);\n }\n const aliasKey = target.toLowerCase();\n if (index.entries.has(aliasKey)) {\n return index.entries.get(aliasKey);\n }\n return target.replace(/\\\\/g, \"/\");\n}\nfunction toVaultId(vaultPath, filePath) {\n const relative2 = path.relative(vaultPath, filePath).replace(/\\.md$/, \"\");\n return relative2.split(path.sep).join(\"/\");\n}\nfunction logSuggestions(filePath, suggestions) {\n if (suggestions.length === 0) return;\n console.log(`\n\\u{1F4A1} Suggested links in ${path.basename(filePath)}`);\n for (const suggestion of suggestions) {\n console.log(` Line ${suggestion.line}: \"${suggestion.alias}\" \\u2192 [[${suggestion.path}]]`);\n }\n}\nasync function linkFile(filePath, index, suggestionIndex, dryRun) {\n const content = fs.readFileSync(filePath, \"utf-8\");\n const linkedContent = autoLink(content, index);\n const suggestions = findUnlinkedMentions(linkedContent, suggestionIndex);\n if (dryRun) {\n const matches = dryRunLink(content, index);\n if (matches.length > 0) {\n console.log(`\n\\u{1F4C4} ${filePath}`);\n for (const m of matches) {\n console.log(` Line ${m.line}: \"${m.alias}\" \\u2192 [[${m.path}]]`);\n }\n }\n logSuggestions(filePath, suggestions);\n return matches.length;\n }\n if (linkedContent !== content) {\n fs.writeFileSync(filePath, linkedContent);\n const matches = dryRunLink(content, index);\n console.log(`\\u2713 Linked ${matches.length} entities in ${path.basename(filePath)}`);\n logSuggestions(filePath, suggestions);\n return matches.length;\n }\n logSuggestions(filePath, suggestions);\n return 0;\n}\nasync function linkAllFiles(vaultPath, index, suggestionIndex, dryRun) {\n const files = [];\n function walk(dir) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (!entry.name.startsWith(\".\") && entry.name !== \"archive\" && entry.name !== \"templates\") {\n walk(fullPath);\n }\n } else if (entry.name.endsWith(\".md\")) {\n files.push(fullPath);\n }\n }\n }\n walk(vaultPath);\n let totalLinks = 0;\n let filesModified = 0;\n for (const file of files) {\n const links = await linkFile(file, index, suggestionIndex, dryRun);\n if (links > 0) {\n totalLinks += links;\n filesModified++;\n }\n }\n console.log(`\n${dryRun ? \"(dry run) \" : \"\"}${totalLinks} links in ${filesModified} files`);\n}\nexport {\n linkCommand\n};\n",848 "inputSchema": {},849 "outputSchema": null,850 "icons": null,851 "annotations": null,852 "meta": null,853 "execution": null854 },855 {856 "name": "sleep.d.ts",857 "title": null,858 "description": "Script: sleep.d.ts. Code:\nimport { H as HandoffDocument, D as Document } from '../types-DO8rJ490.js';\n\ntype PromptFn = (question: string) => Promise<string>;\ninterface SleepOptions {\n workingOn: string;\n next?: string;\n blocked?: string;\n decisions?: string;\n questions?: string;\n feeling?: string;\n sessionKey?: string;\n vaultPath: string;\n index?: boolean;\n git?: boolean;\n prompt?: PromptFn;\n cwd?: string;\n}\ninterface GitCommitResult {\n repoRoot?: string;\n dirtyCount?: number;\n committed: boolean;\n message?: string;\n skippedReason?: string;\n}\ninterface SleepResult {\n handoff: HandoffDocument;\n document: Document;\n git?: GitCommitResult;\n}\ndeclare function sleep(options: SleepOptions): Promise<SleepResult>;\n\nexport { type GitCommitResult, type PromptFn, type SleepOptions, type SleepResult, sleep };\n",859 "inputSchema": {},860 "outputSchema": null,861 "icons": null,862 "annotations": null,863 "meta": null,864 "execution": null865 },866 {867 "name": "template.d.ts",868 "title": null,869 "description": "Script: template.d.ts. Code:\nimport { TemplateVariables } from '../lib/template-engine.js';\n\ninterface TemplateCommandContext {\n vaultPath?: string;\n cwd?: string;\n builtinDir?: string;\n}\ninterface TemplateCreateOptions extends TemplateCommandContext {\n title?: string;\n type?: string;\n}\ninterface TemplateAddOptions extends TemplateCommandContext {\n name: string;\n overwrite?: boolean;\n}\ndeclare function listTemplates(options?: TemplateCommandContext): string[];\ndeclare function createFromTemplate(name: string, options?: TemplateCreateOptions): {\n outputPath: string;\n templatePath: string;\n variables: TemplateVariables;\n};\ndeclare function addTemplate(file: string, options: TemplateAddOptions): {\n templatePath: string;\n name: string;\n};\n\nexport { type TemplateAddOptions, type TemplateCommandContext, type TemplateCreateOptions, addTemplate, createFromTemplate, listTemplates };\n",870 "inputSchema": {},871 "outputSchema": null,872 "icons": null,873 "annotations": null,874 "meta": null,875 "execution": null876 },877 {878 "name": "wake.d.ts",879 "title": null,880 "description": "Script: wake.d.ts. Code:\nimport { e as SessionRecap } from '../types-DO8rJ490.js';\nimport { RecoveryInfo } from './recover.js';\nimport './checkpoint.js';\n\ninterface WakeOptions {\n vaultPath: string;\n handoffLimit?: number;\n brief?: boolean;\n}\ninterface WakeResult {\n recovery: RecoveryInfo;\n recap: SessionRecap;\n recapMarkdown: string;\n summary: string;\n}\ndeclare function buildWakeSummary(recovery: RecoveryInfo, recap: SessionRecap): string;\ndeclare function wake(options: WakeOptions): Promise<WakeResult>;\n\nexport { type WakeOptions, type WakeResult, buildWakeSummary, wake };\n",881 "inputSchema": {},882 "outputSchema": null,883 "icons": null,884 "annotations": null,885 "meta": null,886 "execution": null887 },888 {889 "name": "recover.js",890 "title": null,891 "description": "Script: recover.js. Code:\nimport {\n formatRecoveryInfo,\n recover\n} from \"../chunk-MILVYUPK.js\";\nimport \"../chunk-MZZJLQNQ.js\";\nimport \"../chunk-7ZRP733D.js\";\nexport {\n formatRecoveryInfo,\n recover\n};\n",892 "inputSchema": {},893 "outputSchema": null,894 "icons": null,895 "annotations": null,896 "meta": null,897 "execution": null898 },899 {900 "name": "doctor.js",901 "title": null,902 "description": "Script: doctor.js. Code:\nimport {\n ClawVault,\n findVault\n} from \"../chunk-MXNXWOPL.js\";\nimport {\n scanVaultLinks\n} from \"../chunk-4VQTUVH7.js\";\nimport \"../chunk-J7ZWCI2C.js\";\nimport {\n formatAge\n} from \"../chunk-7ZRP733D.js\";\nimport {\n hasQmd\n} from \"../chunk-VJIFT5T5.js\";\n\n// src/commands/doctor.ts\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nvar CLAWVAULT_DIR = \".clawvault\";\nvar CHECKPOINT_FILE = \"last-checkpoint.json\";\nvar DAY_MS = 24 * 60 * 60 * 1e3;\nvar ACTIVE_USE_DAYS = 7;\nfunction daysSince(date, now = Date.now()) {\n return Math.max(0, Math.floor((now - date.getTime()) / DAY_MS));\n}\nfunction describeAge(date, now = Date.now()) {\n return formatAge(now - date.getTime());\n}\nfunction loadCheckpointTimestamp(vaultPath) {\n const checkpointPath = path.join(vaultPath, CLAWVAULT_DIR, CHECKPOINT_FILE);\n if (!fs.existsSync(checkpointPath)) {\n return {};\n }\n try {\n const data = JSON.parse(fs.readFileSync(checkpointPath, \"utf-8\"));\n return { timestamp: data.timestamp };\n } catch (err) {\n return { error: err?.message || \"Failed to parse checkpoint\" };\n }\n}\nfunction getShellConfigPaths(shellPath) {\n const home = os.homedir();\n const shellName = shellPath ? path.basename(shellPath) : \"bash\";\n if (shellName === \"zsh\") {\n return [path.join(home, \".zshrc\"), path.join(home, \".zprofile\")];\n }\n if (shellName === \"fish\") {\n return [path.join(home, \".config\", \"fish\", \"config.fish\")];\n }\n return [path.join(home, \".bashrc\"), path.join(home, \".bash_profile\"), path.join(home, \".profile\")];\n}\nfunction hasClawvaultPathConfig(paths) {\n for (const filePath of paths) {\n if (!fs.existsSync(filePath)) continue;\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n if (/CLAWVAULT_PATH\\s*=/.test(content)) {\n return true;\n }\n } catch {\n }\n }\n return false;\n}\nasync function resolveVault(vaultPath) {\n if (vaultPath) {\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n return vault;\n }\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n const vault = new ClawVault(path.resolve(envPath));\n await vault.load();\n return vault;\n }\n const found = await findVault();\n if (!found) {\n throw new Error(\"No ClawVault found. Run `clawvault init` first.\");\n }\n return found;\n}\nasync function doctor(vaultPath) {\n const checks = [];\n let warnings = 0;\n let errors = 0;\n if (hasQmd()) {\n checks.push({ label: \"qmd installed\", status: \"ok\" });\n } else {\n checks.push({\n label: \"qmd installed\",\n status: \"error\",\n hint: \"Install qmd to enable ClawVault commands.\"\n });\n errors++;\n }\n const shellConfigs = getShellConfigPaths(process.env.SHELL).filter(fs.existsSync);\n if (hasClawvaultPathConfig(shellConfigs)) {\n checks.push({\n label: \"CLAWVAULT_PATH in shell config\",\n status: \"ok\",\n detail: shellConfigs.map((p) => path.basename(p)).join(\", \")\n });\n } else {\n checks.push({\n label: \"CLAWVAULT_PATH in shell config\",\n status: \"warn\",\n hint: \"Run `clawvault shell-init` and add it to your shell rc.\"\n });\n warnings++;\n }\n if (!hasQmd()) {\n return { vaultPath, checks, warnings, errors };\n }\n let vault;\n try {\n vault = await resolveVault(vaultPath);\n checks.push({ label: \"vault found\", status: \"ok\", detail: vault.getPath() });\n } catch (err) {\n checks.push({\n label: \"vault found\",\n status: \"error\",\n detail: err?.message || \"Unable to locate vault\"\n });\n errors++;\n return { vaultPath, checks, warnings, errors };\n }\n const stats = await vault.stats();\n const documents = await vault.list();\n const handoffs = await vault.list(\"handoffs\");\n const inbox = await vault.list(\"inbox\");\n const qmdCollection = vault.getQmdCollection();\n if (qmdCollection) {\n checks.push({ label: \"qmd collection configured\", status: \"ok\", detail: qmdCollection });\n } else {\n checks.push({\n label: \"qmd collection configured\",\n status: \"warn\",\n hint: \"Set qmd collection in .clawvault.json\"\n });\n warnings++;\n }\n const latestDoc = documents.slice().sort((a, b) => b.modified.getTime() - a.modified.getTime())[0];\n const latestDocAge = latestDoc ? daysSince(latestDoc.modified) : null;\n let lastHandoffAge = null;\n if (handoffs.length === 0) {\n checks.push({\n label: \"recent handoff\",\n status: \"warn\",\n hint: \"Run `clawvault sleep` at the end of sessions.\"\n });\n warnings++;\n } else {\n const latestHandoff = handoffs.slice().sort((a, b) => b.modified.getTime() - a.modified.getTime())[0];\n lastHandoffAge = daysSince(latestHandoff.modified);\n const ageLabel = describeAge(latestHandoff.modified);\n if (lastHandoffAge > 1) {\n checks.push({\n label: \"recent handoff\",\n status: \"warn\",\n detail: `Last handoff ${ageLabel} ago`,\n hint: \"Run `clawvault sleep` before long pauses.\"\n });\n warnings++;\n } else {\n checks.push({\n label: \"recent handoff\",\n status: \"ok\",\n detail: `Last handoff ${ageLabel} ago`\n });\n }\n }\n const checkpointInfo = loadCheckpointTimestamp(vault.getPath());\n const activeUse = latestDocAge !== null && latestDocAge <= ACTIVE_USE_DAYS || lastHandoffAge !== null && lastHandoffAge <= ACTIVE_USE_DAYS;\n if (checkpointInfo.error) {\n checks.push({\n label: \"checkpoint freshness\",\n status: \"warn\",\n detail: checkpointInfo.error\n });\n warnings++;\n } else if (!checkpointInfo.timestamp) {\n const status = activeUse ? \"warn\" : \"ok\";\n if (status === \"warn\") warnings++;\n checks.push({\n label: \"checkpoint freshness\",\n status,\n detail: activeUse ? \"No checkpoint found\" : \"No checkpoint found (vault appears inactive)\",\n hint: activeUse ? \"Run `clawvault checkpoint` during heavy work.\" : void 0\n });\n } else {\n const checkpointDate = new Date(checkpointInfo.timestamp);\n const checkpointAge = daysSince(checkpointDate);\n const ageLabel = describeAge(checkpointDate);\n if (activeUse && checkpointAge > 1) {\n checks.push({\n label: \"checkpoint freshness\",\n status: \"warn\",\n detail: `Last checkpoint ${ageLabel} ago`,\n hint: \"Checkpoint at least once per active day.\"\n });\n warnings++;\n } else {\n checks.push({\n label: \"checkpoint freshness\",\n status: \"ok\",\n detail: `Last checkpoint ${ageLabel} ago`\n });\n }\n }\n const linkScan = scanVaultLinks(vault.getPath());\n if (linkScan.orphans.length > 20) {\n checks.push({\n label: \"orphan links\",\n status: \"warn\",\n detail: `${linkScan.orphans.length} orphan link(s)`,\n hint: \"Run `clawvault link --orphans` to review.\"\n });\n warnings++;\n } else {\n checks.push({\n label: \"orphan links\",\n status: \"ok\",\n detail: `${linkScan.orphans.length} orphan link(s)`\n });\n }\n if (inbox.length > 5) {\n checks.push({\n label: \"inbox backlog\",\n status: \"warn\",\n detail: `${inbox.length} inbox item(s) pending`,\n hint: \"Process inbox items to keep memory tidy.\"\n });\n warnings++;\n } else {\n checks.push({\n label: \"inbox backlog\",\n status: \"ok\",\n detail: `${inbox.length} inbox item(s) pending`\n });\n }\n if (stats.documents < 5) {\n checks.push({\n label: \"vault activity\",\n status: \"warn\",\n detail: `${stats.documents} total documents`,\n hint: \"Start capturing decisions, lessons, and projects.\"\n });\n warnings++;\n }\n return { vaultPath: vault.getPath(), checks, warnings, errors };\n}\nexport {\n doctor\n};\n",903 "inputSchema": {},904 "outputSchema": null,905 "icons": null,906 "annotations": null,907 "meta": null,908 "execution": null909 },910 {911 "name": "entities.js",912 "title": null,913 "description": "Script: entities.js. Code:\nimport {\n getVaultPath\n} from \"../chunk-4KDZZW4X.js\";\nimport {\n buildEntityIndex\n} from \"../chunk-J7ZWCI2C.js\";\n\n// src/commands/entities.ts\nasync function entitiesCommand(options) {\n const vaultPath = getVaultPath();\n const index = buildEntityIndex(vaultPath);\n if (options.json) {\n const output = {};\n for (const [path, entry] of index.byPath) {\n output[path] = entry.aliases;\n }\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n const byFolder = {};\n for (const [path, entry] of index.byPath) {\n const folder = path.split(\"/\")[0];\n if (!byFolder[folder]) byFolder[folder] = [];\n byFolder[folder].push({ path, aliases: entry.aliases });\n }\n console.log(\"\\u{1F4DA} Linkable Entities\\n\");\n for (const [folder, entities] of Object.entries(byFolder)) {\n console.log(`## ${folder}/`);\n for (const entity of entities) {\n const name = entity.path.split(\"/\")[1];\n const otherAliases = entity.aliases.filter((a) => a.toLowerCase() !== name.toLowerCase());\n if (otherAliases.length > 0) {\n console.log(` - ${name} (${otherAliases.join(\", \")})`);\n } else {\n console.log(` - ${name}`);\n }\n }\n console.log();\n }\n console.log(`Total: ${index.byPath.size} entities, ${index.entries.size} linkable aliases`);\n}\nexport {\n entitiesCommand\n};\n",914 "inputSchema": {},915 "outputSchema": null,916 "icons": null,917 "annotations": null,918 "meta": null,919 "execution": null920 },921 {922 "name": "repair-session.js",923 "title": null,924 "description": "Script: repair-session.js. Code:\nimport {\n analyzeSession,\n repairSession\n} from \"../chunk-L53L5FCL.js\";\nimport {\n findMainSession,\n findSessionById,\n listAgents\n} from \"../chunk-AZRV2I5U.js\";\n\n// src/commands/repair-session.ts\nimport * as fs from \"fs\";\nfunction resolveSession(options) {\n const { sessionId, agentId } = options;\n if (sessionId && agentId) {\n return findSessionById(agentId, sessionId);\n }\n if (sessionId) {\n const agents = listAgents();\n for (const agent of agents) {\n const session = findSessionById(agent, sessionId);\n if (session) return session;\n }\n return null;\n }\n if (agentId) {\n return findMainSession(agentId);\n }\n const defaultAgent = process.env.OPENCLAW_AGENT_ID || \"clawdious\";\n return findMainSession(defaultAgent);\n}\nfunction formatRepairResult(result, options = {}) {\n const { dryRun = false } = options;\n const lines = [];\n lines.push(`Analyzing session: ${result.sessionId}`);\n lines.push(\"\");\n if (result.corruptedEntries.length === 0) {\n lines.push(\"\\u2705 No corruption detected. Session is clean.\");\n return lines.join(\"\\n\");\n }\n if (dryRun) {\n lines.push(`Found ${result.corruptedEntries.length} corrupted entries:`);\n } else {\n lines.push(`Found and fixed ${result.corruptedEntries.length} corrupted entries:`);\n }\n for (const entry of result.corruptedEntries) {\n const prefix = entry.type === \"aborted_tool_use\" ? \"Aborted tool_use\" : \"Orphaned tool_result\";\n lines.push(` - Line ${entry.lineNumber}: ${prefix} (id: ${entry.toolUseId})`);\n }\n if (result.parentRelinks.length > 0) {\n lines.push(\"\");\n if (dryRun) {\n lines.push(`Would relink ${result.parentRelinks.length} parent reference(s):`);\n } else {\n lines.push(`Relinked ${result.parentRelinks.length} parent reference(s):`);\n }\n for (const relink of result.parentRelinks.slice(0, 5)) {\n lines.push(` - Line ${relink.lineNumber}: parentId ${relink.oldParentId.slice(0, 8)}\\u2026 \\u2192 ${relink.newParentId === \"null\" ? \"null\" : relink.newParentId.slice(0, 8)}\\u2026`);\n }\n if (result.parentRelinks.length > 5) {\n lines.push(` ... and ${result.parentRelinks.length - 5} more`);\n }\n }\n lines.push(\"\");\n if (dryRun) {\n lines.push(`Would remove ${result.removedCount} entries, relink ${result.relinkedCount} parent references.`);\n } else {\n lines.push(`\\u2705 Session repaired: removed ${result.removedCount} entries, relinked ${result.relinkedCount} parent references`);\n if (result.backupPath) {\n const backupName = result.backupPath.split(\"/\").pop();\n lines.push(`Backup saved: ${backupName}`);\n }\n }\n return lines.join(\"\\n\");\n}\nasync function repairSessionCommand(options) {\n const { backup = true, dryRun = false } = options;\n const session = resolveSession(options);\n if (!session) {\n throw new Error(\n options.sessionId ? `Session not found: ${options.sessionId}` : options.agentId ? `No main session found for agent: ${options.agentId}` : \"No session found. Specify --session or --agent.\"\n );\n }\n if (!fs.existsSync(session.filePath)) {\n throw new Error(`Session file not found: ${session.filePath}`);\n }\n if (dryRun) {\n return analyzeSession(session.filePath);\n }\n return repairSession(session.filePath, { backup, dryRun: false });\n}\nfunction listAgentSessions(agentId) {\n const agents = agentId ? [agentId] : listAgents();\n const lines = [];\n if (agents.length === 0) {\n return \"No agents found in ~/.openclaw/agents/\";\n }\n for (const agent of agents) {\n const mainSession = findMainSession(agent);\n if (mainSession) {\n lines.push(`${agent}:`);\n lines.push(` Main session: ${mainSession.sessionId}`);\n lines.push(` File: ${mainSession.filePath}`);\n if (mainSession.updatedAt) {\n const date = new Date(mainSession.updatedAt);\n lines.push(` Updated: ${date.toISOString()}`);\n }\n lines.push(\"\");\n }\n }\n if (lines.length === 0) {\n return agentId ? `No sessions found for agent: ${agentId}` : \"No sessions found.\";\n }\n return lines.join(\"\\n\");\n}\nexport {\n formatRepairResult,\n listAgentSessions,\n repairSessionCommand,\n resolveSession\n};\n",925 "inputSchema": {},926 "outputSchema": null,927 "icons": null,928 "annotations": null,929 "meta": null,930 "execution": null931 },932 {933 "name": "shell-init.d.ts",934 "title": null,935 "description": "Script: shell-init.d.ts. Code:\ninterface ShellInitOptions {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n}\ndeclare function shellInit(options?: ShellInitOptions): string;\n\nexport { type ShellInitOptions, shellInit };\n",936 "inputSchema": {},937 "outputSchema": null,938 "icons": null,939 "annotations": null,940 "meta": null,941 "execution": null942 },943 {944 "name": "link.d.ts",945 "title": null,946 "description": "Script: link.d.ts. Code:\ninterface LinkOptions {\n all?: boolean;\n dryRun?: boolean;\n backlinks?: string;\n orphans?: boolean;\n rebuild?: boolean;\n}\ndeclare function linkCommand(file: string | undefined, options: LinkOptions): Promise<void>;\n\nexport { linkCommand };\n",947 "inputSchema": {},948 "outputSchema": null,949 "icons": null,950 "annotations": null,951 "meta": null,952 "execution": null953 },954 {955 "name": "wake.js",956 "title": null,957 "description": "Script: wake.js. Code:\nimport {\n ClawVault\n} from \"../chunk-MXNXWOPL.js\";\nimport {\n recover\n} from \"../chunk-MILVYUPK.js\";\nimport {\n clearDirtyFlag\n} from \"../chunk-MZZJLQNQ.js\";\nimport \"../chunk-7ZRP733D.js\";\nimport \"../chunk-VJIFT5T5.js\";\n\n// src/commands/wake.ts\nimport * as path from \"path\";\nvar DEFAULT_HANDOFF_LIMIT = 3;\nfunction formatSummaryItems(items, maxItems = 2) {\n const cleaned = items.map((item) => item.trim()).filter(Boolean);\n if (cleaned.length === 0) return \"\";\n if (cleaned.length <= maxItems) return cleaned.join(\", \");\n return `${cleaned.slice(0, maxItems).join(\", \")} +${cleaned.length - maxItems} more`;\n}\nfunction buildWakeSummary(recovery, recap) {\n if (recovery.checkpoint?.workingOn) {\n return recovery.checkpoint.workingOn;\n }\n const latestHandoff = recap.recentHandoffs[0];\n if (latestHandoff?.workingOn?.length) {\n return formatSummaryItems(latestHandoff.workingOn);\n }\n if (recap.activeProjects.length > 0) {\n return formatSummaryItems(recap.activeProjects);\n }\n return \"No recent work summary found.\";\n}\nasync function wake(options) {\n const vaultPath = path.resolve(options.vaultPath);\n const recovery = await recover(vaultPath, { clearFlag: true });\n await clearDirtyFlag(vaultPath);\n const vault = new ClawVault(vaultPath);\n await vault.load();\n const recap = await vault.generateRecap({\n handoffLimit: options.handoffLimit ?? DEFAULT_HANDOFF_LIMIT,\n brief: options.brief ?? true\n });\n const summary = buildWakeSummary(recovery, recap);\n const recapMarkdown = vault.formatRecap(recap, { brief: options.brief ?? true });\n return {\n recovery,\n recap,\n recapMarkdown,\n summary\n };\n}\nexport {\n buildWakeSummary,\n wake\n};\n",958 "inputSchema": {},959 "outputSchema": null,960 "icons": null,961 "annotations": null,962 "meta": null,963 "execution": null964 },965 {966 "name": "recover.d.ts",967 "title": null,968 "description": "Script: recover.d.ts. Code:\nimport { CheckpointData } from './checkpoint.js';\n\n/**\n * Recovery command - detect dirty death and provide recovery info\n */\n\ninterface RecoveryInfo {\n died: boolean;\n deathTime: string | null;\n checkpoint: CheckpointData | null;\n handoffPath: string | null;\n handoffContent: string | null;\n recoveryMessage: string;\n}\ndeclare function recover(vaultPath: string, options?: {\n clearFlag?: boolean;\n verbose?: boolean;\n}): Promise<RecoveryInfo>;\n/**\n * Format recovery info for CLI output\n */\ndeclare function formatRecoveryInfo(info: RecoveryInfo, options?: {\n verbose?: boolean;\n}): string;\n\nexport { type RecoveryInfo, formatRecoveryInfo, recover };\n",969 "inputSchema": {},970 "outputSchema": null,971 "icons": null,972 "annotations": null,973 "meta": null,974 "execution": null975 },976 {977 "name": "shell-init.js",978 "title": null,979 "description": "Script: shell-init.js. Code:\n// src/commands/shell-init.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nfunction detectVaultPath(startPath) {\n let current = path.resolve(startPath);\n while (true) {\n const configPath = path.join(current, \".clawvault.json\");\n if (fs.existsSync(configPath)) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\nfunction shellQuote(value) {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\nfunction shellInit(options = {}) {\n const env = options.env ?? process.env;\n const cwd = options.cwd ?? process.cwd();\n const detected = env.CLAWVAULT_PATH || detectVaultPath(cwd);\n const lines = [];\n lines.push(\"# ClawVault shell integration\");\n if (detected) {\n lines.push('if [ -z \"$CLAWVAULT_PATH\" ]; then');\n lines.push(` export CLAWVAULT_PATH=${shellQuote(path.resolve(detected))}`);\n lines.push(\"fi\");\n } else {\n lines.push(\"# Set CLAWVAULT_PATH to your vault directory:\");\n lines.push('# export CLAWVAULT_PATH=\"/path/to/vault\"');\n }\n lines.push(\"alias cvwake='clawvault wake'\");\n lines.push(\"alias cvsleep='clawvault sleep'\");\n lines.push(\"alias cvcheck='clawvault doctor'\");\n return lines.join(\"\\n\");\n}\nexport {\n shellInit\n};\n",980 "inputSchema": {},981 "outputSchema": null,982 "icons": null,983 "annotations": null,984 "meta": null,985 "execution": null986 },987 {988 "name": "status.js",989 "title": null,990 "description": "Script: status.js. Code:\nimport {\n ClawVault\n} from \"../chunk-MXNXWOPL.js\";\nimport {\n scanVaultLinks\n} from \"../chunk-4VQTUVH7.js\";\nimport \"../chunk-J7ZWCI2C.js\";\nimport {\n formatAge\n} from \"../chunk-7ZRP733D.js\";\nimport {\n QmdUnavailableError,\n hasQmd\n} from \"../chunk-VJIFT5T5.js\";\n\n// src/commands/status.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { execFileSync } from \"child_process\";\nvar CLAWVAULT_DIR = \".clawvault\";\nvar CHECKPOINT_FILE = \"last-checkpoint.json\";\nvar DIRTY_DEATH_FLAG = \"dirty-death.flag\";\nfunction findGitRoot(startPath) {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, \".git\"))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\nfunction getGitStatus(repoRoot) {\n const output = execFileSync(\"git\", [\"-C\", repoRoot, \"status\", \"--porcelain\"], {\n encoding: \"utf-8\"\n });\n const lines = output.split(\"\\n\").filter(Boolean);\n return { clean: lines.length === 0, dirtyCount: lines.length };\n}\nfunction parseQmdCollectionsText(raw) {\n const names = [];\n const regex = /^(\\S+)\\s+\\(qmd:\\/\\/\\1\\/\\)/gm;\n let match;\n while ((match = regex.exec(raw)) !== null) {\n names.push(match[1]);\n }\n return names;\n}\nfunction getQmdIndexStatus(collection, root) {\n const output = execFileSync(\"qmd\", [\"collection\", \"list\"], { encoding: \"utf-8\" });\n const names = parseQmdCollectionsText(output);\n if (names.includes(collection)) {\n return \"present\";\n }\n return \"missing\";\n}\nfunction loadCheckpoint(vaultPath) {\n const checkpointPath = path.join(vaultPath, CLAWVAULT_DIR, CHECKPOINT_FILE);\n if (!fs.existsSync(checkpointPath)) {\n return { data: null };\n }\n try {\n const data = JSON.parse(fs.readFileSync(checkpointPath, \"utf-8\"));\n return { data };\n } catch (err) {\n return { data: null, error: err?.message || \"Failed to parse checkpoint\" };\n }\n}\nasync function getStatus(vaultPath) {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n const vault = new ClawVault(path.resolve(vaultPath));\n await vault.load();\n const stats = await vault.stats();\n const linkScan = scanVaultLinks(vault.getPath());\n const issues = [];\n const checkpointInfo = loadCheckpoint(vault.getPath());\n const checkpoint = checkpointInfo.data;\n if (checkpointInfo.error) {\n issues.push(`Checkpoint parse error: ${checkpointInfo.error}`);\n }\n const checkpointStatus = {\n exists: Boolean(checkpoint),\n timestamp: checkpoint?.timestamp,\n age: checkpoint?.timestamp ? formatAge(Date.now() - new Date(checkpoint.timestamp).getTime()) : void 0,\n sessionKey: checkpoint?.sessionKey,\n model: checkpoint?.model,\n tokenEstimate: checkpoint?.tokenEstimate\n };\n if (!checkpointStatus.exists) {\n issues.push(\"No checkpoint found\");\n }\n const dirtyFlagPath = path.join(vault.getPath(), CLAWVAULT_DIR, DIRTY_DEATH_FLAG);\n if (fs.existsSync(dirtyFlagPath)) {\n issues.push(\"Dirty death flag is set\");\n }\n const qmdCollection = vault.getQmdCollection();\n const qmdRoot = vault.getQmdRoot();\n let qmdIndexStatus = \"missing\";\n let qmdError;\n try {\n qmdIndexStatus = getQmdIndexStatus(qmdCollection, qmdRoot);\n if (qmdIndexStatus !== \"present\") {\n issues.push(`qmd collection ${qmdIndexStatus.replace(\"-\", \" \")}`);\n }\n } catch (err) {\n qmdError = err?.message || \"Failed to check qmd index\";\n issues.push(`qmd status error: ${qmdError}`);\n }\n let gitStatus;\n const gitRoot = findGitRoot(vault.getPath());\n if (gitRoot) {\n try {\n const gitInfo = getGitStatus(gitRoot);\n gitStatus = { repoRoot: gitRoot, ...gitInfo };\n if (!gitInfo.clean) {\n issues.push(`Uncommitted changes: ${gitInfo.dirtyCount}`);\n }\n } catch (err) {\n issues.push(`Git status error: ${err?.message || \"unknown error\"}`);\n }\n }\n return {\n vaultName: vault.getName(),\n vaultPath: vault.getPath(),\n health: issues.length === 0 ? \"ok\" : \"warning\",\n issues,\n checkpoint: checkpointStatus,\n qmd: {\n collection: qmdCollection,\n root: qmdRoot,\n indexStatus: qmdIndexStatus,\n error: qmdError\n },\n git: gitStatus,\n links: {\n total: linkScan.linkCount,\n orphans: linkScan.orphans.length\n },\n documents: stats.documents,\n categories: stats.categories\n };\n}\nfunction formatStatus(status) {\n let output = \"ClawVault Status\\n\";\n output += \"-\".repeat(40) + \"\\n\";\n output += `Vault: ${status.vaultName}\n`;\n output += `Path: ${status.vaultPath}\n`;\n output += `Health: ${status.health}\n`;\n if (status.issues.length > 0) {\n output += `Issues: ${status.issues.join(\"; \")}\n`;\n } else {\n output += \"Issues: none\\n\";\n }\n output += \"\\nCheckpoint:\\n\";\n if (!status.checkpoint.exists) {\n output += \" - none\\n\";\n } else {\n output += ` - Timestamp: ${status.checkpoint.timestamp}\n`;\n if (status.checkpoint.age) {\n output += ` - Age: ${status.checkpoint.age}\n`;\n }\n if (status.checkpoint.sessionKey) {\n output += ` - Session key: ${status.checkpoint.sessionKey}\n`;\n }\n if (status.checkpoint.model) {\n output += ` - Model: ${status.checkpoint.model}\n`;\n }\n if (status.checkpoint.tokenEstimate !== void 0) {\n output += ` - Token estimate: ${status.checkpoint.tokenEstimate}\n`;\n }\n }\n output += \"\\nqmd:\\n\";\n output += ` - Collection: ${status.qmd.collection}\n`;\n output += ` - Root: ${status.qmd.root}\n`;\n output += ` - Index: ${status.qmd.indexStatus}\n`;\n if (status.qmd.error) {\n output += ` - Error: ${status.qmd.error}\n`;\n }\n if (status.git) {\n output += \"\\nGit:\\n\";\n output += ` - Repo: ${status.git.repoRoot}\n`;\n output += ` - Status: ${status.git.clean ? \"clean\" : \"dirty\"} (${status.git.dirtyCount} change(s))\n`;\n }\n output += \"\\nLinks:\\n\";\n output += ` - Total: ${status.links.total}\n`;\n if (status.links.orphans > 0) {\n output += ` - Orphans: ${status.links.orphans}\n`;\n }\n output += \"\\nDocuments:\\n\";\n output += ` - Total: ${status.documents}\n`;\n output += \" - By category:\\n\";\n for (const [category, count] of Object.entries(status.categories)) {\n output += ` * ${category}: ${count}\n`;\n }\n output += \"-\".repeat(40) + \"\\n\";\n return output;\n}\nasync function statusCommand(vaultPath, options = {}) {\n const status = await getStatus(vaultPath);\n if (options.json) {\n console.log(JSON.stringify(status, null, 2));\n return;\n }\n console.log(formatStatus(status));\n}\nexport {\n formatStatus,\n getStatus,\n statusCommand\n};\n",991 "inputSchema": {},992 "outputSchema": null,993 "icons": null,994 "annotations": null,995 "meta": null,996 "execution": null997 },998 {999 "name": "template.js",1000 "title": null,1001 "description": "Script: template.js. Code:\nimport {\n buildTemplateVariables,\n renderTemplate\n} from \"../chunk-7766SIJP.js\";\n\n// src/commands/template.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { fileURLToPath } from \"url\";\nvar VAULT_CONFIG_FILE = \".clawvault.json\";\nvar TEMPLATE_EXTENSION = \".md\";\nfunction resolveBuiltinTemplatesDir(override) {\n if (override) {\n const resolved = path.resolve(override);\n return fs.existsSync(resolved) ? resolved : null;\n }\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(moduleDir, \"../templates\"),\n path.resolve(moduleDir, \"../../templates\")\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {\n return candidate;\n }\n }\n return null;\n}\nfunction findVaultRoot(start) {\n let current = path.resolve(start);\n while (true) {\n if (fs.existsSync(path.join(current, VAULT_CONFIG_FILE))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\nfunction resolveVaultPath(options) {\n if (options.vaultPath) {\n return path.resolve(options.vaultPath);\n }\n const envPath = process.env.CLAWVAULT_PATH;\n if (envPath) {\n return path.resolve(envPath);\n }\n const cwd = options.cwd ?? process.cwd();\n return findVaultRoot(cwd);\n}\nfunction normalizeTemplateName(name) {\n const base = path.basename(name, path.extname(name));\n return base.trim();\n}\nfunction slugify(text) {\n return text.toLowerCase().replace(/[^\\w\\s-]/g, \"\").replace(/\\s+/g, \"-\").replace(/-+/g, \"-\").trim();\n}\nfunction listTemplateFiles(dir, ignore) {\n const entries = /* @__PURE__ */ new Map();\n if (!fs.existsSync(dir)) return entries;\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(TEMPLATE_EXTENSION)) continue;\n const name = normalizeTemplateName(entry.name);\n if (!name) continue;\n if (ignore?.has(name)) continue;\n entries.set(name, path.join(dir, entry.name));\n }\n return entries;\n}\nfunction buildTemplateIndex(options) {\n const index = /* @__PURE__ */ new Map();\n const builtinDir = resolveBuiltinTemplatesDir(options.builtinDir);\n if (builtinDir) {\n const ignore = /* @__PURE__ */ new Set([\"daily\"]);\n for (const [name, filePath] of listTemplateFiles(builtinDir, ignore)) {\n index.set(name, filePath);\n }\n }\n const vaultPath = resolveVaultPath(options);\n if (vaultPath) {\n const vaultTemplatesDir = path.join(vaultPath, \"templates\");\n for (const [name, filePath] of listTemplateFiles(vaultTemplatesDir)) {\n index.set(name, filePath);\n }\n }\n return index;\n}\nfunction listTemplates(options = {}) {\n const index = buildTemplateIndex(options);\n return [...index.keys()].sort();\n}\nfunction createFromTemplate(name, options = {}) {\n const templateName = normalizeTemplateName(name);\n if (!templateName) {\n throw new Error(\"Template name is required.\");\n }\n const index = buildTemplateIndex(options);\n const templatePath = index.get(templateName);\n if (!templatePath) {\n const available = [...index.keys()].sort();\n const hint = available.length > 0 ? ` Available: ${available.join(\", \")}` : \"\";\n throw new Error(`Template not found: ${templateName}.${hint}`);\n }\n const raw = fs.readFileSync(templatePath, \"utf-8\");\n const now = /* @__PURE__ */ new Date();\n const date = now.toISOString().split(\"T\")[0];\n const type = options.type ?? templateName;\n const title = options.title ?? `${type} ${date}`.trim();\n const variables = buildTemplateVariables({ title, type, date }, now);\n const rendered = renderTemplate(raw, variables);\n const cwd = options.cwd ?? process.cwd();\n const slug = slugify(title) || slugify(templateName) || `template-${date}`;\n const outputPath = path.join(cwd, `${slug}${TEMPLATE_EXTENSION}`);\n if (fs.existsSync(outputPath)) {\n throw new Error(`File already exists: ${outputPath}`);\n }\n fs.writeFileSync(outputPath, rendered);\n return { outputPath, templatePath, variables };\n}\nfunction addTemplate(file, options) {\n const name = normalizeTemplateName(options.name);\n if (!name) {\n throw new Error(\"Template name is required.\");\n }\n const vaultPath = resolveVaultPath(options);\n if (!vaultPath) {\n throw new Error(\"No vault found. Set CLAWVAULT_PATH or use --vault.\");\n }\n const cwd = options.cwd ?? process.cwd();\n const sourcePath = path.resolve(cwd, file);\n if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isFile()) {\n throw new Error(`Template file not found: ${sourcePath}`);\n }\n const templatesDir = path.join(vaultPath, \"templates\");\n fs.mkdirSync(templatesDir, { recursive: true });\n const targetPath = path.join(templatesDir, `${name}${TEMPLATE_EXTENSION}`);\n if (fs.existsSync(targetPath) && !options.overwrite) {\n throw new Error(`Template already exists: ${targetPath}`);\n }\n fs.copyFileSync(sourcePath, targetPath);\n return { templatePath: targetPath, name };\n}\nexport {\n addTemplate,\n createFromTemplate,\n listTemplates\n};\n",1002 "inputSchema": {},1003 "outputSchema": null,1004 "icons": null,1005 "annotations": null,1006 "meta": null,1007 "execution": null1008 },1009 {1010 "name": "repair-session.d.ts",1011 "title": null,1012 "description": "Script: repair-session.d.ts. Code:\nimport { SessionInfo } from '../lib/session-utils.js';\nimport { RepairResult } from '../lib/session-repair.js';\n\n/**\n * repair-session command - Repair corrupted OpenClaw session transcripts\n *\n * Fixes issues like:\n * - Aborted tool calls with partial JSON\n * - Orphaned tool_result messages referencing non-existent tool_use IDs\n * - Broken parent chain references\n */\n\ninterface RepairSessionOptions {\n sessionId?: string;\n agentId?: string;\n backup?: boolean;\n dryRun?: boolean;\n}\n/**\n * Resolve the session to repair\n */\ndeclare function resolveSession(options: RepairSessionOptions): SessionInfo | null;\n/**\n * Format repair result for CLI output\n */\ndeclare function formatRepairResult(result: RepairResult, options?: {\n dryRun?: boolean;\n}): string;\n/**\n * Main repair-session command handler\n */\ndeclare function repairSessionCommand(options: RepairSessionOptions): Promise<RepairResult>;\n/**\n * List available sessions for an agent (for --list flag)\n */\ndeclare function listAgentSessions(agentId?: string): string;\n\nexport { type RepairSessionOptions, formatRepairResult, listAgentSessions, repairSessionCommand, resolveSession };\n",1013 "inputSchema": {},1014 "outputSchema": null,1015 "icons": null,1016 "annotations": null,1017 "meta": null,1018 "execution": null1019 },1020 {1021 "name": "status.d.ts",1022 "title": null,1023 "description": "Script: status.d.ts. Code:\ninterface VaultStatus {\n vaultName: string;\n vaultPath: string;\n health: 'ok' | 'warning';\n issues: string[];\n checkpoint: {\n exists: boolean;\n timestamp?: string;\n age?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n };\n qmd: {\n collection: string;\n root: string;\n indexStatus: 'present' | 'missing' | 'root-mismatch';\n error?: string;\n };\n git?: {\n repoRoot: string;\n clean: boolean;\n dirtyCount: number;\n };\n links: {\n total: number;\n orphans: number;\n };\n documents: number;\n categories: Record<string, number>;\n}\ndeclare function getStatus(vaultPath: string): Promise<VaultStatus>;\ndeclare function formatStatus(status: VaultStatus): string;\ndeclare function statusCommand(vaultPath: string, options?: {\n json?: boolean;\n}): Promise<void>;\n\nexport { type VaultStatus, formatStatus, getStatus, statusCommand };\n",1024 "inputSchema": {},1025 "outputSchema": null,1026 "icons": null,1027 "annotations": null,1028 "meta": null,1029 "execution": null1030 },1031 {1032 "name": "setup.d.ts",1033 "title": null,1034 "description": "Script: setup.d.ts. Code:\ndeclare function setupCommand(): Promise<void>;\n\nexport { setupCommand };\n",1035 "inputSchema": {},1036 "outputSchema": null,1037 "icons": null,1038 "annotations": null,1039 "meta": null,1040 "execution": null1041 },1042 {1043 "name": "entities.d.ts",1044 "title": null,1045 "description": "Script: entities.d.ts. Code:\ninterface EntitiesOptions {\n json?: boolean;\n}\ndeclare function entitiesCommand(options: EntitiesOptions): Promise<void>;\n\nexport { entitiesCommand };\n",1046 "inputSchema": {},1047 "outputSchema": null,1048 "icons": null,1049 "annotations": null,1050 "meta": null,1051 "execution": null1052 },1053 {1054 "name": "doctor.d.ts",1055 "title": null,1056 "description": "Script: doctor.d.ts. Code:\ntype DoctorStatus = 'ok' | 'warn' | 'error';\ninterface DoctorCheck {\n label: string;\n status: DoctorStatus;\n detail?: string;\n hint?: string;\n}\ninterface DoctorReport {\n vaultPath?: string;\n checks: DoctorCheck[];\n warnings: number;\n errors: number;\n}\ndeclare function doctor(vaultPath?: string): Promise<DoctorReport>;\n\nexport { type DoctorCheck, type DoctorReport, type DoctorStatus, doctor };\n",1057 "inputSchema": {},1058 "outputSchema": null,1059 "icons": null,1060 "annotations": null,1061 "meta": null,1062 "execution": null1063 },1064 {1065 "name": "checkpoint.d.ts",1066 "title": null,1067 "description": "Script: checkpoint.d.ts. Code:\n/**\n * Quick checkpoint command - fast state save for context death resilience\n */\ninterface CheckpointOptions {\n workingOn?: string;\n focus?: string;\n blocked?: string;\n vaultPath: string;\n urgent?: boolean;\n}\ninterface CheckpointData {\n timestamp: string;\n workingOn: string | null;\n focus: string | null;\n blocked: string | null;\n sessionId?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n sessionStartedAt?: string;\n urgent?: boolean;\n}\ninterface SessionState {\n sessionId?: string;\n sessionKey?: string;\n model?: string;\n tokenEstimate?: number;\n startedAt?: string;\n}\ndeclare function flush(): Promise<CheckpointData | null>;\ndeclare function checkpoint(options: CheckpointOptions): Promise<CheckpointData>;\ndeclare function clearDirtyFlag(vaultPath: string): Promise<void>;\ndeclare function cleanExit(vaultPath: string): Promise<void>;\ndeclare function checkDirtyDeath(vaultPath: string): Promise<{\n died: boolean;\n checkpoint: CheckpointData | null;\n deathTime: string | null;\n}>;\ndeclare function setSessionState(vaultPath: string, session: string | SessionState): Promise<void>;\n\nexport { type CheckpointData, type CheckpointOptions, type SessionState, checkDirtyDeath, checkpoint, cleanExit, clearDirtyFlag, flush, setSessionState };\n",1068 "inputSchema": {},1069 "outputSchema": null,1070 "icons": null,1071 "annotations": null,1072 "meta": null,1073 "execution": null1074 },1075 {1076 "name": "setup.js",1077 "title": null,1078 "description": "Script: setup.js. Code:\nimport {\n setupCommand\n} from \"../chunk-QYJI73KF.js\";\nimport \"../chunk-VJIFT5T5.js\";\nexport {\n setupCommand\n};\n",1079 "inputSchema": {},1080 "outputSchema": null,1081 "icons": null,1082 "annotations": null,1083 "meta": null,1084 "execution": null1085 },1086 {1087 "name": "checkpoint.js",1088 "title": null,1089 "description": "Script: checkpoint.js. Code:\nimport {\n checkDirtyDeath,\n checkpoint,\n cleanExit,\n clearDirtyFlag,\n flush,\n setSessionState\n} from \"../chunk-MZZJLQNQ.js\";\nexport {\n checkDirtyDeath,\n checkpoint,\n cleanExit,\n clearDirtyFlag,\n flush,\n setSessionState\n};\n",1090 "inputSchema": {},1091 "outputSchema": null,1092 "icons": null,1093 "annotations": null,1094 "meta": null,1095 "execution": null1096 },1097 {1098 "name": "sleep.js",1099 "title": null,1100 "description": "Script: sleep.js. Code:\nimport {\n ClawVault\n} from \"../chunk-MXNXWOPL.js\";\nimport {\n clearDirtyFlag\n} from \"../chunk-MZZJLQNQ.js\";\nimport {\n qmdUpdate\n} from \"../chunk-VJIFT5T5.js\";\n\n// src/commands/sleep.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as readline from \"readline\";\nimport { execFileSync } from \"child_process\";\nfunction isInteractive() {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\nasync function defaultPrompt(question) {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve2) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve2(answer.trim());\n });\n });\n}\nfunction parseList(raw) {\n if (!raw) return [];\n return raw.split(\",\").map((item) => item.trim()).filter(Boolean);\n}\nfunction ensureNonEmpty(label, items) {\n if (items.length === 0) {\n throw new Error(`${label} is required.`);\n }\n}\nasync function promptForList(label, prompt, interactive) {\n if (!interactive) return [];\n const answer = await prompt(`${label} (comma-separated, empty to skip): `);\n return parseList(answer);\n}\nfunction findGitRoot(startPath) {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, \".git\"))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\nfunction getGitStatus(repoRoot) {\n const output = execFileSync(\"git\", [\"-C\", repoRoot, \"status\", \"--porcelain\"], {\n encoding: \"utf-8\"\n });\n const lines = output.split(\"\\n\").filter(Boolean);\n return { clean: lines.length === 0, dirtyCount: lines.length };\n}\nfunction isAffirmative(input) {\n const normalized = input.trim().toLowerCase();\n return normalized === \"y\" || normalized === \"yes\";\n}\nasync function maybeCommitDirtyRepo(options) {\n if (!options.enabled) {\n return { committed: false, skippedReason: \"disabled\" };\n }\n const repoRoot = findGitRoot(options.cwd);\n if (!repoRoot) {\n return { committed: false, skippedReason: \"no-repo\" };\n }\n let status;\n try {\n status = getGitStatus(repoRoot);\n } catch (err) {\n if (err?.code === \"ENOENT\") {\n return { committed: false, skippedReason: \"git-missing\" };\n }\n return { repoRoot, committed: false, skippedReason: \"status-error\" };\n }\n if (status.clean) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: \"clean\" };\n }\n if (!options.interactive) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: \"non-interactive\" };\n }\n const confirm = await options.prompt(\n `Git repo dirty (${status.dirtyCount} change(s)). Commit before sleep? (y/N): `\n );\n if (!isAffirmative(confirm)) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: \"declined\" };\n }\n const message = await options.prompt(\"Commit message: \");\n if (!message) {\n return { repoRoot, dirtyCount: status.dirtyCount, committed: false, skippedReason: \"no-message\" };\n }\n try {\n execFileSync(\"git\", [\"-C\", repoRoot, \"add\", \"-A\"], { stdio: \"inherit\" });\n execFileSync(\"git\", [\"-C\", repoRoot, \"commit\", \"-m\", message], { stdio: \"inherit\" });\n } catch (err) {\n throw new Error(`Git commit failed: ${err?.message || \"unknown error\"}`);\n }\n return {\n repoRoot,\n dirtyCount: status.dirtyCount,\n committed: true,\n message\n };\n}\nasync function sleep(options) {\n const prompt = options.prompt ?? defaultPrompt;\n const interactive = isInteractive();\n const workingOn = parseList(options.workingOn);\n ensureNonEmpty(\"Working-on summary\", workingOn);\n const nextProvided = options.next !== void 0;\n const blockedProvided = options.blocked !== void 0;\n let nextSteps = parseList(options.next);\n let blocked = parseList(options.blocked);\n if (!nextProvided) {\n nextSteps = await promptForList(\"Next steps\", prompt, interactive);\n }\n if (!blockedProvided) {\n blocked = await promptForList(\"Blocked items\", prompt, interactive);\n }\n const decisions = parseList(options.decisions);\n const questions = parseList(options.questions);\n const vault = new ClawVault(path.resolve(options.vaultPath));\n await vault.load();\n const handoffInput = {\n workingOn,\n blocked,\n nextSteps,\n decisions: decisions.length > 0 ? decisions : void 0,\n openQuestions: questions.length > 0 ? questions : void 0,\n feeling: options.feeling,\n sessionKey: options.sessionKey\n };\n const document = await vault.createHandoff(handoffInput);\n const handoff = {\n ...handoffInput,\n created: document.modified.toISOString()\n };\n await clearDirtyFlag(vault.getPath());\n if (options.index) {\n qmdUpdate(vault.getQmdCollection());\n }\n const git = await maybeCommitDirtyRepo({\n enabled: options.git !== false,\n prompt,\n cwd: options.cwd ?? process.cwd(),\n interactive\n });\n return { handoff, document, git };\n}\nexport {\n sleep\n};\n",1101 "inputSchema": {},1102 "outputSchema": null,1103 "icons": null,1104 "annotations": null,1105 "meta": null,1106 "execution": null1107 },1108 {1109 "name": "chunk-MILVYUPK.js",1110 "title": null,1111 "description": "Script: chunk-MILVYUPK.js. Code:\nimport {\n checkDirtyDeath,\n clearDirtyFlag\n} from \"./chunk-MZZJLQNQ.js\";\nimport {\n formatAge\n} from \"./chunk-7ZRP733D.js\";\n\n// src/commands/recover.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nasync function recover(vaultPath, options = {}) {\n const { clearFlag = false } = options;\n const { died, checkpoint, deathTime } = await checkDirtyDeath(vaultPath);\n if (!died) {\n return {\n died: false,\n deathTime: null,\n checkpoint: null,\n handoffPath: null,\n handoffContent: null,\n recoveryMessage: \"No context death detected. Clean startup.\"\n };\n }\n const handoffsDir = path.join(vaultPath, \"handoffs\");\n let handoffPath = null;\n let handoffContent = null;\n if (fs.existsSync(handoffsDir)) {\n const files = fs.readdirSync(handoffsDir).filter((f) => f.startsWith(\"handoff-\") && f.endsWith(\".md\")).sort().reverse();\n if (files.length > 0) {\n handoffPath = path.join(handoffsDir, files[0]);\n handoffContent = fs.readFileSync(handoffPath, \"utf-8\");\n }\n }\n let message = \"\\u26A0\\uFE0F **CONTEXT DEATH DETECTED**\\n\\n\";\n message += `Your previous session died at ${deathTime}.\n\n`;\n if (checkpoint) {\n message += \"**Last known state:**\\n\";\n if (checkpoint.workingOn) {\n message += `- Working on: ${checkpoint.workingOn}\n`;\n }\n if (checkpoint.focus) {\n message += `- Focus: ${checkpoint.focus}\n`;\n }\n if (checkpoint.blocked) {\n message += `- Blocked: ${checkpoint.blocked}\n`;\n }\n message += \"\\n\";\n }\n if (handoffPath) {\n message += `**Last handoff:** ${path.basename(handoffPath)}\n`;\n message += \"Review and resume from where you left off.\\n\";\n } else {\n message += \"**No handoff found.** You may have lost context.\\n\";\n }\n if (clearFlag) {\n await clearDirtyFlag(vaultPath);\n }\n return {\n died: true,\n deathTime,\n checkpoint,\n handoffPath,\n handoffContent,\n recoveryMessage: message\n };\n}\nfunction formatRecoveryInfo(info, options = {}) {\n const { verbose = false } = options;\n if (!info.died) {\n return \"\\u2713 Clean startup - no context death detected.\";\n }\n let output = \"\\n\\u26A0\\uFE0F CONTEXT DEATH DETECTED\\n\";\n output += \"\\u2550\".repeat(40) + \"\\n\\n\";\n output += `Death time: ${info.deathTime}\n`;\n if (info.checkpoint?.timestamp) {\n const age = formatAge(Date.now() - new Date(info.checkpoint.timestamp).getTime());\n output += `Checkpoint: ${info.checkpoint.timestamp} (${age} ago)\n`;\n }\n output += \"\\n\";\n if (info.checkpoint) {\n output += \"Last checkpoint:\\n\";\n if (info.checkpoint.workingOn) {\n output += ` \\u2022 Working on: ${info.checkpoint.workingOn}\n`;\n }\n if (info.checkpoint.focus) {\n output += ` \\u2022 Focus: ${info.checkpoint.focus}\n`;\n }\n if (info.checkpoint.blocked) {\n output += ` \\u2022 Blocked: ${info.checkpoint.blocked}\n`;\n }\n if (info.checkpoint.sessionKey || info.checkpoint.model || info.checkpoint.tokenEstimate !== void 0) {\n output += \" \\u2022 Session:\\n\";\n if (info.checkpoint.sessionKey) {\n output += ` - Key: ${info.checkpoint.sessionKey}\n`;\n }\n if (info.checkpoint.model) {\n output += ` - Model: ${info.checkpoint.model}\n`;\n }\n if (info.checkpoint.tokenEstimate !== void 0) {\n output += ` - Token estimate: ${info.checkpoint.tokenEstimate}\n`;\n }\n }\n output += \"\\n\";\n } else {\n output += \"No checkpoint data found.\\n\\n\";\n }\n if (info.handoffPath) {\n output += `Last handoff: ${path.basename(info.handoffPath)}\n`;\n } else {\n output += \"No handoff found - context may be lost.\\n\";\n }\n if (verbose) {\n if (info.checkpoint) {\n output += \"\\nCheckpoint JSON:\\n\";\n output += JSON.stringify(info.checkpoint, null, 2) + \"\\n\";\n }\n if (info.handoffContent) {\n output += \"\\nHandoff content:\\n\";\n output += info.handoffContent.trim() + \"\\n\";\n }\n }\n output += \"\\n\" + \"\\u2550\".repeat(40) + \"\\n\";\n output += \"Run `clawvault recap` to see full context.\\n\";\n return output;\n}\n\nexport {\n recover,\n formatRecoveryInfo\n};\n",1112 "inputSchema": {},1113 "outputSchema": null,1114 "icons": null,1115 "annotations": null,1116 "meta": null,1117 "execution": null1118 },1119 {1120 "name": "chunk-4KDZZW4X.js",1121 "title": null,1122 "description": "Script: chunk-4KDZZW4X.js. Code:\n// src/lib/config.ts\nimport * as path from \"path\";\nfunction getVaultPath() {\n const vaultPath = process.env.CLAWVAULT_PATH;\n if (!vaultPath) {\n throw new Error(\"CLAWVAULT_PATH environment variable not set\");\n }\n return path.resolve(vaultPath);\n}\n\nexport {\n getVaultPath\n};\n",1123 "inputSchema": {},1124 "outputSchema": null,1125 "icons": null,1126 "annotations": null,1127 "meta": null,1128 "execution": null1129 },1130 {1131 "name": "chunk-AZRV2I5U.js",1132 "title": null,1133 "description": "Script: chunk-AZRV2I5U.js. Code:\n// src/lib/session-utils.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nfunction getOpenClawAgentsDir() {\n return path.join(os.homedir(), \".openclaw\", \"agents\");\n}\nfunction getSessionsDir(agentId) {\n return path.join(getOpenClawAgentsDir(), agentId, \"sessions\");\n}\nfunction getSessionsJsonPath(agentId) {\n return path.join(getSessionsDir(agentId), \"sessions.json\");\n}\nfunction getSessionFilePath(agentId, sessionId) {\n return path.join(getSessionsDir(agentId), `${sessionId}.jsonl`);\n}\nfunction listAgents() {\n const agentsDir = getOpenClawAgentsDir();\n if (!fs.existsSync(agentsDir)) {\n return [];\n }\n return fs.readdirSync(agentsDir).filter((name) => {\n const sessionsDir = getSessionsDir(name);\n return fs.existsSync(sessionsDir) && fs.statSync(sessionsDir).isDirectory();\n });\n}\nfunction loadSessionsStore(agentId) {\n const sessionsJsonPath = getSessionsJsonPath(agentId);\n if (!fs.existsSync(sessionsJsonPath)) {\n return null;\n }\n try {\n const content = fs.readFileSync(sessionsJsonPath, \"utf-8\");\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\nfunction findMainSession(agentId) {\n const store = loadSessionsStore(agentId);\n if (!store) return null;\n const mainKey = `agent:${agentId}:main`;\n const entry = store[mainKey];\n if (entry?.sessionId) {\n const filePath = getSessionFilePath(agentId, entry.sessionId);\n if (fs.existsSync(filePath)) {\n return {\n sessionId: entry.sessionId,\n sessionKey: mainKey,\n agentId,\n filePath,\n updatedAt: entry.updatedAt\n };\n }\n }\n return null;\n}\nfunction findSessionById(agentId, sessionId) {\n const filePath = getSessionFilePath(agentId, sessionId);\n if (!fs.existsSync(filePath)) {\n return null;\n }\n const store = loadSessionsStore(agentId);\n let sessionKey;\n let updatedAt;\n if (store) {\n for (const [key, entry] of Object.entries(store)) {\n if (entry.sessionId === sessionId) {\n sessionKey = key;\n updatedAt = entry.updatedAt;\n break;\n }\n }\n }\n return {\n sessionId,\n sessionKey: sessionKey || `agent:${agentId}:unknown`,\n agentId,\n filePath,\n updatedAt\n };\n}\nfunction listSessions(agentId) {\n const sessionsDir = getSessionsDir(agentId);\n if (!fs.existsSync(sessionsDir)) {\n return [];\n }\n const store = loadSessionsStore(agentId);\n const sessions = [];\n const files = fs.readdirSync(sessionsDir).filter((f) => f.endsWith(\".jsonl\") && !f.includes(\".backup\") && !f.includes(\".deleted\") && !f.includes(\".corrupted\"));\n for (const file of files) {\n const sessionId = file.replace(\".jsonl\", \"\");\n const filePath = path.join(sessionsDir, file);\n let sessionKey = `agent:${agentId}:unknown`;\n let updatedAt;\n if (store) {\n for (const [key, entry] of Object.entries(store)) {\n if (entry.sessionId === sessionId) {\n sessionKey = key;\n updatedAt = entry.updatedAt;\n break;\n }\n }\n }\n sessions.push({\n sessionId,\n sessionKey,\n agentId,\n filePath,\n updatedAt\n });\n }\n return sessions.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n}\nfunction backupSession(filePath) {\n const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, \"\").replace(\"T\", \"-\").slice(0, 15);\n const backupPath = `${filePath}.backup-${timestamp}`;\n fs.copyFileSync(filePath, backupPath);\n return backupPath;\n}\n\nexport {\n getOpenClawAgentsDir,\n getSessionsDir,\n getSessionsJsonPath,\n getSessionFilePath,\n listAgents,\n loadSessionsStore,\n findMainSession,\n findSessionById,\n listSessions,\n backupSession\n};\n",1134 "inputSchema": {},1135 "outputSchema": null,1136 "icons": null,1137 "annotations": null,1138 "meta": null,1139 "execution": null1140 },1141 {1142 "name": "chunk-4VQTUVH7.js",1143 "title": null,1144 "description": "Script: chunk-4VQTUVH7.js. Code:\nimport {\n buildEntityIndex\n} from \"./chunk-J7ZWCI2C.js\";\n\n// src/lib/backlinks.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nvar CLAWVAULT_DIR = \".clawvault\";\nvar BACKLINKS_FILE = \"backlinks.json\";\nvar WIKI_LINK_REGEX = /\\[\\[([^\\]]+)\\]\\]/g;\nfunction ensureClawvaultDir(vaultPath) {\n const dir = path.join(vaultPath, CLAWVAULT_DIR);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\nfunction toVaultId(vaultPath, filePath) {\n const relative2 = path.relative(vaultPath, filePath).replace(/\\.md$/, \"\");\n return relative2.split(path.sep).join(\"/\");\n}\nfunction normalizeLinkTarget(raw) {\n let target = raw.trim();\n if (!target) return \"\";\n if (target.startsWith(\"[[\") && target.endsWith(\"]]\")) {\n target = target.slice(2, -2);\n }\n const pipeIndex = target.indexOf(\"|\");\n if (pipeIndex !== -1) {\n target = target.slice(0, pipeIndex);\n }\n if (target.startsWith(\"#\")) return \"\";\n const hashIndex = target.indexOf(\"#\");\n if (hashIndex !== -1) {\n target = target.slice(0, hashIndex);\n }\n target = target.trim();\n if (!target) return \"\";\n if (target.endsWith(\".md\")) {\n target = target.slice(0, -3);\n }\n if (target.startsWith(\"/\")) {\n target = target.slice(1);\n }\n return target.replace(/\\\\/g, \"/\");\n}\nfunction listMarkdownFiles(vaultPath) {\n const files = [];\n const skipDirs = /* @__PURE__ */ new Set([\"archive\", \"templates\", \"node_modules\"]);\n function walk(dir) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name.startsWith(\".\") || skipDirs.has(entry.name)) continue;\n walk(fullPath);\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n files.push(fullPath);\n }\n }\n }\n walk(vaultPath);\n return files;\n}\nfunction buildKnownIds(vaultPath, files) {\n const ids = /* @__PURE__ */ new Set();\n const idsLower = /* @__PURE__ */ new Map();\n for (const file of files) {\n const id = toVaultId(vaultPath, file);\n ids.add(id);\n const lower = id.toLowerCase();\n if (!idsLower.has(lower)) {\n idsLower.set(lower, id);\n }\n }\n return { ids, idsLower };\n}\nfunction resolveTarget(target, known, entityIndex) {\n if (!target) return null;\n if (known.ids.has(target)) return target;\n const lower = target.toLowerCase();\n if (known.idsLower.has(lower)) return known.idsLower.get(lower);\n if (entityIndex?.entries.has(lower)) return entityIndex.entries.get(lower);\n return null;\n}\nfunction scanVaultLinks(vaultPath, options = {}) {\n const files = listMarkdownFiles(vaultPath);\n const known = buildKnownIds(vaultPath, files);\n const entityIndex = options.entityIndex ?? buildEntityIndex(vaultPath);\n const backlinks = /* @__PURE__ */ new Map();\n const orphans = [];\n let linkCount = 0;\n for (const file of files) {\n const sourceId = toVaultId(vaultPath, file);\n const content = fs.readFileSync(file, \"utf-8\");\n const matches = content.match(WIKI_LINK_REGEX) || [];\n linkCount += matches.length;\n for (const match of matches) {\n const target = normalizeLinkTarget(match);\n if (!target) continue;\n const resolved = resolveTarget(target, known, entityIndex);\n if (!resolved) {\n orphans.push({ source: sourceId, target });\n continue;\n }\n if (!backlinks.has(resolved)) {\n backlinks.set(resolved, /* @__PURE__ */ new Set());\n }\n backlinks.get(resolved).add(sourceId);\n }\n }\n const backlinksMap = /* @__PURE__ */ new Map();\n for (const [target, sources] of backlinks) {\n backlinksMap.set(target, [...sources].sort());\n }\n return { backlinks: backlinksMap, orphans, linkCount };\n}\nfunction writeBacklinksIndex(vaultPath, backlinks) {\n const dir = ensureClawvaultDir(vaultPath);\n const output = {};\n const targets = [...backlinks.keys()].sort();\n for (const target of targets) {\n const sources = backlinks.get(target) || [];\n output[target] = [...new Set(sources)].sort();\n }\n fs.writeFileSync(path.join(dir, BACKLINKS_FILE), JSON.stringify(output, null, 2));\n}\nfunction readBacklinksIndex(vaultPath) {\n const filePath = path.join(vaultPath, CLAWVAULT_DIR, BACKLINKS_FILE);\n if (!fs.existsSync(filePath)) return null;\n try {\n const raw = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n const map = /* @__PURE__ */ new Map();\n for (const [target, sources] of Object.entries(raw)) {\n if (Array.isArray(sources)) {\n map.set(target, sources);\n }\n }\n return map;\n } catch {\n return null;\n }\n}\nfunction rebuildBacklinksIndex(vaultPath, options = {}) {\n const result = scanVaultLinks(vaultPath, options);\n writeBacklinksIndex(vaultPath, result.backlinks);\n return result;\n}\n\nexport {\n scanVaultLinks,\n readBacklinksIndex,\n rebuildBacklinksIndex\n};\n",1145 "inputSchema": {},1146 "outputSchema": null,1147 "icons": null,1148 "annotations": null,1149 "meta": null,1150 "execution": null1151 },1152 {1153 "name": "chunk-J7ZWCI2C.js",1154 "title": null,1155 "description": "Script: chunk-J7ZWCI2C.js. Code:\n// src/lib/entity-index.ts\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport matter from \"gray-matter\";\nfunction buildEntityIndex(vaultPath) {\n const entries = /* @__PURE__ */ new Map();\n const byPath = /* @__PURE__ */ new Map();\n const entityFolders = [\"people\", \"projects\", \"agents\", \"lessons\", \"decisions\", \"commitments\"];\n for (const folder of entityFolders) {\n const folderPath = path.join(vaultPath, folder);\n if (!fs.existsSync(folderPath)) continue;\n const files = fs.readdirSync(folderPath).filter((f) => f.endsWith(\".md\"));\n for (const file of files) {\n const filePath = path.join(folderPath, file);\n const content = fs.readFileSync(filePath, \"utf-8\");\n const { data: frontmatter } = matter(content);\n const relativePath = `${folder}/${file.replace(\".md\", \"\")}`;\n const baseName = file.replace(\".md\", \"\");\n const aliases = [baseName];\n if (frontmatter.title && frontmatter.title.toLowerCase() !== baseName.toLowerCase()) {\n aliases.push(frontmatter.title);\n }\n if (Array.isArray(frontmatter.aliases)) {\n aliases.push(...frontmatter.aliases);\n }\n for (const alias of aliases) {\n const key = alias.toLowerCase();\n if (!entries.has(key)) {\n entries.set(key, relativePath);\n }\n }\n byPath.set(relativePath, { path: relativePath, aliases });\n }\n }\n return { entries, byPath };\n}\nfunction getSortedAliases(index) {\n const result = [];\n for (const [alias, path2] of index.entries) {\n result.push({ alias, path: path2 });\n }\n result.sort((a, b) => b.alias.length - a.alias.length);\n return result;\n}\n\nexport {\n buildEntityIndex,\n getSortedAliases\n};\n",1156 "inputSchema": {},1157 "outputSchema": null,1158 "icons": null,1159 "annotations": null,1160 "meta": null,1161 "execution": null1162 },1163 {1164 "name": "types-DO8rJ490.d.ts",1165 "title": null,1166 "description": "Script: types-DO8rJ490.d.ts. Code:\n/**\n * ClawVault Types - The elephant's memory structure\n */\ninterface VaultConfig {\n /** Root path of the vault */\n path: string;\n /** Name of the vault */\n name: string;\n /** Categories to create on init */\n categories: string[];\n /** qmd collection name (defaults to vault name if not set) */\n qmdCollection?: string;\n /** Root path for qmd collection (defaults to vault path) */\n qmdRoot?: string;\n /** Custom templates path (optional) */\n templatesPath?: string;\n}\ninterface VaultMeta {\n name: string;\n version: string;\n created: string;\n lastUpdated: string;\n categories: string[];\n documentCount: number;\n /** qmd collection name (defaults to vault name if not set) */\n qmdCollection?: string;\n /** Root path for qmd collection (defaults to vault path) */\n qmdRoot?: string;\n}\ninterface Document {\n /** Unique ID (relative path without extension) */\n id: string;\n /** Full file path */\n path: string;\n /** Category (folder name) */\n category: string;\n /** Document title */\n title: string;\n /** Raw content */\n content: string;\n /** Frontmatter metadata */\n frontmatter: Record<string, unknown>;\n /** Extracted wiki-links [[like-this]] */\n links: string[];\n /** Tags extracted from content */\n tags: string[];\n /** Last modified timestamp */\n modified: Date;\n}\ninterface SearchResult {\n /** Document that matched */\n document: Document;\n /** Relevance score (0-1) */\n score: number;\n /** Matching snippet */\n snippet: string;\n /** Which terms matched */\n matchedTerms: string[];\n}\ninterface SearchOptions {\n /** Max results to return */\n limit?: number;\n /** Minimum score threshold (0-1) */\n minScore?: number;\n /** Filter by category */\n category?: string;\n /** Filter by tags */\n tags?: string[];\n /** Include full content in results */\n fullContent?: boolean;\n}\ninterface StoreOptions {\n /** Category to store in */\n category: string;\n /** Document title (used for filename) */\n title: string;\n /** Content body */\n content: string;\n /** Frontmatter metadata */\n frontmatter?: Record<string, unknown>;\n /** Override existing file */\n overwrite?: boolean;\n /** Trigger qmd update after storing */\n qmdUpdate?: boolean;\n /** Trigger qmd embed after storing (implies qmdUpdate) */\n qmdEmbed?: boolean;\n}\ninterface SyncOptions {\n /** Target directory to sync to */\n target: string;\n /** Delete files in target not in source */\n deleteOrphans?: boolean;\n /** Dry run - don't actually sync */\n dryRun?: boolean;\n}\ninterface SyncResult {\n copied: string[];\n deleted: string[];\n unchanged: string[];\n errors: string[];\n}\ntype Category = 'preferences' | 'decisions' | 'patterns' | 'people' | 'projects' | 'goals' | 'transcripts' | 'inbox' | 'templates' | 'facts' | 'feelings' | 'lessons' | 'commitments' | 'handoffs' | string;\ndeclare const DEFAULT_CATEGORIES: Category[];\n/**\n * Memory Type Taxonomy (Benthic's 8 categories)\n * Knowing WHAT KIND of thing helps you know WHERE to put it\n */\ntype MemoryType = 'fact' | 'feeling' | 'decision' | 'lesson' | 'commitment' | 'preference' | 'relationship' | 'project';\ndeclare const MEMORY_TYPES: MemoryType[];\n/**\n * Memory type to category mapping\n */\ndeclare const TYPE_TO_CATEGORY: Record<MemoryType, Category>;\n/**\n * Handoff document - bridges sessions\n */\ninterface HandoffDocument {\n /** When this handoff was created */\n created: string;\n /** Session key or identifier */\n sessionKey?: string;\n /** What I was working on */\n workingOn: string[];\n /** What is currently blocked */\n blocked: string[];\n /** What comes next */\n nextSteps: string[];\n /** Emotional state/energy */\n feeling?: string;\n /** Key decisions made */\n decisions?: string[];\n /** Open questions */\n openQuestions?: string[];\n}\n/**\n * Session recap - who I was when I woke up\n */\ninterface SessionRecap {\n /** When recap was generated */\n generated: string;\n /** Recent handoffs (last N) */\n recentHandoffs: HandoffDocument[];\n /** Active projects */\n activeProjects: string[];\n /** Pending commitments */\n pendingCommitments: string[];\n /** Recent decisions made */\n recentDecisions?: string[];\n /** Recent lessons learned */\n recentLessons: string[];\n /** Key relationships to remember */\n keyRelationships: string[];\n /** Current emotional arc */\n emotionalArc?: string;\n}\ndeclare const DEFAULT_CONFIG: Partial<VaultConfig>;\n\nexport { type Category as C, type Document as D, type HandoffDocument as H, type MemoryType as M, type StoreOptions as S, TYPE_TO_CATEGORY as T, type VaultConfig as V, type SearchOptions as a, type SearchResult as b, type SyncOptions as c, type SyncResult as d, type SessionRecap as e, DEFAULT_CATEGORIES as f, DEFAULT_CONFIG as g, MEMORY_TYPES as h, type VaultMeta as i };\n",1167 "inputSchema": {},1168 "outputSchema": null,1169 "icons": null,1170 "annotations": null,1171 "meta": null,1172 "execution": null1173 },1174 {1175 "name": "index.js",1176 "title": null,1177 "description": "Script: index.js. Code:\nimport {\n buildTemplateVariables,\n renderTemplate\n} from \"./chunk-7766SIJP.js\";\nimport {\n ClawVault,\n createVault,\n findVault\n} from \"./chunk-MXNXWOPL.js\";\nimport {\n setupCommand\n} from \"./chunk-QYJI73KF.js\";\nimport {\n DEFAULT_CATEGORIES,\n DEFAULT_CONFIG,\n MEMORY_TYPES,\n QMD_INSTALL_COMMAND,\n QMD_INSTALL_URL,\n QmdUnavailableError,\n SearchEngine,\n TYPE_TO_CATEGORY,\n extractTags,\n extractWikiLinks,\n hasQmd,\n qmdEmbed,\n qmdUpdate\n} from \"./chunk-VJIFT5T5.js\";\n\n// src/index.ts\nimport * as fs from \"fs\";\nfunction readPackageVersion() {\n try {\n const pkgUrl = new URL(\"../package.json\", import.meta.url);\n const pkg = JSON.parse(fs.readFileSync(pkgUrl, \"utf-8\"));\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\nvar VERSION = readPackageVersion();\nexport {\n ClawVault,\n DEFAULT_CATEGORIES,\n DEFAULT_CONFIG,\n MEMORY_TYPES,\n QMD_INSTALL_COMMAND,\n QMD_INSTALL_URL,\n QmdUnavailableError,\n SearchEngine,\n TYPE_TO_CATEGORY,\n VERSION,\n buildTemplateVariables,\n createVault,\n extractTags,\n extractWikiLinks,\n findVault,\n hasQmd,\n qmdEmbed,\n qmdUpdate,\n renderTemplate,\n setupCommand\n};\n",1178 "inputSchema": {},1179 "outputSchema": null,1180 "icons": null,1181 "annotations": null,1182 "meta": null,1183 "execution": null1184 },1185 {1186 "name": "chunk-VJIFT5T5.js",1187 "title": null,1188 "description": "Script: chunk-VJIFT5T5.js. Code:\n// src/types.ts\nvar DEFAULT_CATEGORIES = [\n \"preferences\",\n \"decisions\",\n \"patterns\",\n \"people\",\n \"projects\",\n \"goals\",\n \"transcripts\",\n \"inbox\",\n \"templates\"\n];\nvar MEMORY_TYPES = [\n \"fact\",\n \"feeling\",\n \"decision\",\n \"lesson\",\n \"commitment\",\n \"preference\",\n \"relationship\",\n \"project\"\n];\nvar TYPE_TO_CATEGORY = {\n fact: \"facts\",\n feeling: \"feelings\",\n decision: \"decisions\",\n lesson: \"lessons\",\n commitment: \"commitments\",\n preference: \"preferences\",\n relationship: \"people\",\n project: \"projects\"\n};\nvar DEFAULT_CONFIG = {\n categories: DEFAULT_CATEGORIES\n};\n\n// src/lib/search.ts\nimport { execFileSync, spawnSync } from \"child_process\";\nimport * as path from \"path\";\nvar QMD_INSTALL_URL = \"https://github.com/tobi/qmd\";\nvar QMD_INSTALL_COMMAND = \"bun install -g github:tobi/qmd\";\nvar QMD_NOT_INSTALLED_MESSAGE = `ClawVault requires qmd. Install: ${QMD_INSTALL_COMMAND}`;\nvar QmdUnavailableError = class extends Error {\n constructor(message = QMD_NOT_INSTALLED_MESSAGE) {\n super(message);\n this.name = \"QmdUnavailableError\";\n }\n};\nfunction ensureJsonArgs(args) {\n return args.includes(\"--json\") ? args : [...args, \"--json\"];\n}\nfunction tryParseJson(raw) {\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\nfunction extractJsonPayload(raw) {\n const start = raw.search(/[\\[{]/);\n if (start === -1) return null;\n const end = Math.max(raw.lastIndexOf(\"]\"), raw.lastIndexOf(\"}\"));\n if (end <= start) return null;\n return raw.slice(start, end + 1);\n}\nfunction parseQmdOutput(raw) {\n const trimmed = raw.trim();\n if (!trimmed) return [];\n const direct = tryParseJson(trimmed);\n const extracted = direct ? null : extractJsonPayload(trimmed);\n const parsed = direct ?? (extracted ? tryParseJson(extracted) : null);\n if (!parsed) {\n throw new Error(\"qmd returned non-JSON output. Ensure qmd supports --json.\");\n }\n if (Array.isArray(parsed)) {\n return parsed;\n }\n if (parsed && typeof parsed === \"object\") {\n const candidate = parsed.results ?? parsed.items ?? parsed.data;\n if (Array.isArray(candidate)) {\n return candidate;\n }\n }\n throw new Error(\"qmd returned an unexpected JSON shape.\");\n}\nfunction ensureQmdAvailable() {\n if (!hasQmd()) {\n throw new QmdUnavailableError();\n }\n}\nfunction execQmd(args) {\n ensureQmdAvailable();\n const finalArgs = ensureJsonArgs(args);\n try {\n const result = execFileSync(\"qmd\", finalArgs, {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n maxBuffer: 10 * 1024 * 1024\n // 10MB\n });\n return parseQmdOutput(result);\n } catch (err) {\n if (err?.code === \"ENOENT\") {\n throw new QmdUnavailableError();\n }\n const output = [err?.stdout, err?.stderr].filter(Boolean).join(\"\\n\");\n if (output) {\n try {\n return parseQmdOutput(output);\n } catch {\n }\n }\n const message = err?.message ? `qmd failed: ${err.message}` : \"qmd failed\";\n throw new Error(message);\n }\n}\nfunction hasQmd() {\n const result = spawnSync(\"qmd\", [\"--version\"], { stdio: \"ignore\" });\n return !result.error;\n}\nfunction qmdUpdate(collection) {\n ensureQmdAvailable();\n const args = [\"update\"];\n if (collection) {\n args.push(\"-c\", collection);\n }\n execFileSync(\"qmd\", args, { stdio: \"inherit\" });\n}\nfunction qmdEmbed(collection) {\n ensureQmdAvailable();\n const args = [\"embed\"];\n if (collection) {\n args.push(\"-c\", collection);\n }\n execFileSync(\"qmd\", args, { stdio: \"inherit\" });\n}\nvar SearchEngine = class {\n documents = /* @__PURE__ */ new Map();\n collection = \"clawvault\";\n vaultPath = \"\";\n collectionRoot = \"\";\n /**\n * Set the collection name (usually vault name)\n */\n setCollection(name) {\n this.collection = name;\n }\n /**\n * Set the vault path for file resolution\n */\n setVaultPath(vaultPath) {\n this.vaultPath = vaultPath;\n }\n /**\n * Set the collection root for qmd:// URI resolution\n */\n setCollectionRoot(root) {\n this.collectionRoot = path.resolve(root);\n }\n /**\n * Add or update a document in the local cache\n * Note: qmd indexing happens via qmd update command\n */\n addDocument(doc) {\n this.documents.set(doc.id, doc);\n }\n /**\n * Remove a document from the local cache\n */\n removeDocument(id) {\n this.documents.delete(id);\n }\n /**\n * No-op for qmd - indexing is managed externally\n */\n rebuildIDF() {\n }\n /**\n * BM25 search via qmd\n */\n search(query, options = {}) {\n return this.runQmdQuery(\"search\", query, options);\n }\n /**\n * Vector/semantic search via qmd vsearch\n */\n vsearch(query, options = {}) {\n return this.runQmdQuery(\"vsearch\", query, options);\n }\n /**\n * Combined search with query expansion (qmd query command)\n */\n query(query, options = {}) {\n return this.runQmdQuery(\"query\", query, options);\n }\n runQmdQuery(command, query, options) {\n const {\n limit = 10,\n minScore = 0,\n category,\n tags,\n fullContent = false\n } = options;\n if (!query.trim()) return [];\n const args = [\n command,\n query,\n \"-n\",\n String(limit * 2),\n \"--json\"\n ];\n if (this.collection) {\n args.push(\"-c\", this.collection);\n }\n const qmdResults = execQmd(args);\n return this.convertResults(qmdResults, {\n limit,\n minScore,\n category,\n tags,\n fullContent\n });\n }\n /**\n * Convert qmd results to ClawVault SearchResult format\n */\n convertResults(qmdResults, options) {\n const { limit = 10, minScore = 0, category, tags, fullContent = false } = options;\n const results = [];\n const maxScore = qmdResults[0]?.score || 1;\n for (const qr of qmdResults) {\n const filePath = this.qmdUriToPath(qr.file);\n const relativePath = this.vaultPath ? path.relative(this.vaultPath, filePath) : filePath;\n const docId = relativePath.replace(/\\.md$/, \"\");\n let doc = this.documents.get(docId);\n const parts = relativePath.split(path.sep);\n const docCategory = parts.length > 1 ? parts[0] : \"root\";\n if (category && docCategory !== category) continue;\n if (tags && tags.length > 0 && doc) {\n const docTags = new Set(doc.tags);\n if (!tags.some((t) => docTags.has(t))) continue;\n }\n const normalizedScore = maxScore > 0 ? qr.score / maxScore : 0;\n if (normalizedScore < minScore) continue;\n if (!doc) {\n doc = {\n id: docId,\n path: filePath,\n category: docCategory,\n title: qr.title || path.basename(relativePath, \".md\"),\n content: \"\",\n // Content loaded separately if needed\n frontmatter: {},\n links: [],\n tags: [],\n modified: /* @__PURE__ */ new Date()\n };\n }\n results.push({\n document: fullContent ? doc : { ...doc, content: \"\" },\n score: normalizedScore,\n snippet: this.cleanSnippet(qr.snippet),\n matchedTerms: []\n // qmd doesn't provide this\n });\n if (results.length >= limit) break;\n }\n return results;\n }\n /**\n * Convert qmd:// URI to file path\n */\n qmdUriToPath(uri) {\n if (uri.startsWith(\"qmd://\")) {\n const withoutScheme = uri.slice(6);\n const slashIndex = withoutScheme.indexOf(\"/\");\n if (slashIndex > -1) {\n const relativePath = withoutScheme.slice(slashIndex + 1);\n const root = this.collectionRoot || this.vaultPath;\n if (root) {\n return path.join(root, relativePath);\n }\n return relativePath;\n }\n }\n return uri;\n }\n /**\n * Clean up qmd snippet format\n */\n cleanSnippet(snippet) {\n if (!snippet) return \"\";\n return snippet.replace(/@@ [-+]?\\d+,?\\d* @@ \\([^)]+\\)/g, \"\").trim().split(\"\\n\").slice(0, 3).join(\"\\n\").slice(0, 300);\n }\n /**\n * Get all cached documents\n */\n getAllDocuments() {\n return [...this.documents.values()];\n }\n /**\n * Get document count\n */\n get size() {\n return this.documents.size;\n }\n /**\n * Clear the local document cache\n */\n clear() {\n this.documents.clear();\n }\n /**\n * Export documents for persistence\n */\n export() {\n return {\n documents: [...this.documents.values()]\n };\n }\n /**\n * Import from persisted data\n */\n import(data) {\n this.clear();\n for (const doc of data.documents) {\n this.addDocument(doc);\n }\n }\n};\nfunction extractWikiLinks(content) {\n const matches = content.match(/\\[\\[([^\\]]+)\\]\\]/g) || [];\n return matches.map((m) => m.slice(2, -2).toLowerCase());\n}\nfunction extractTags(content) {\n const matches = content.match(/#[\\w-]+/g) || [];\n return [...new Set(matches.map((m) => m.slice(1).toLowerCase()))];\n}\n\nexport {\n DEFAULT_CATEGORIES,\n MEMORY_TYPES,\n TYPE_TO_CATEGORY,\n DEFAULT_CONFIG,\n QMD_INSTALL_URL,\n QMD_INSTALL_COMMAND,\n QmdUnavailableError,\n hasQmd,\n qmdUpdate,\n qmdEmbed,\n SearchEngine,\n extractWikiLinks,\n extractTags\n};\n",1189 "inputSchema": {},1190 "outputSchema": null,1191 "icons": null,1192 "annotations": null,1193 "meta": null,1194 "execution": null1195 }1196 ]1197 },1198 "error": null1199 }1200 ],1201 "issues": [1202 {1203 "code": "W004",1204 "message": "The MCP server is not in our registry.",1205 "reference": [1206 0,1207 null1208 ],1209 "extra_data": null1210 }1211 ],1212 "labels": [1213 [1214 {1215 "is_public_sink": 0,1216 "destructive": 0,1217 "untrusted_content": 0,1218 "private_data": 01219 },1220 {1221 "is_public_sink": 0,1222 "destructive": 0,1223 "untrusted_content": 0,1224 "private_data": 01225 },1226 {1227 "is_public_sink": 0,1228 "destructive": 0,1229 "untrusted_content": 0,1230 "private_data": 01231 },1232 {1233 "is_public_sink": 0,1234 "destructive": 0,1235 "untrusted_content": 0,1236 "private_data": 01237 },1238 {1239 "is_public_sink": 0,1240 "destructive": 0,1241 "untrusted_content": 0,1242 "private_data": 01243 },1244 {1245 "is_public_sink": 0,1246 "destructive": 0,1247 "untrusted_content": 0,1248 "private_data": 01249 },1250 {1251 "is_public_sink": 0,1252 "destructive": 0,1253 "untrusted_content": 0,1254 "private_data": 01255 },1256 {1257 "is_public_sink": 0,1258 "destructive": 0,1259 "untrusted_content": 0,1260 "private_data": 01261 },1262 {1263 "is_public_sink": 0,1264 "destructive": 0,1265 "untrusted_content": 0,1266 "private_data": 01267 },1268 {1269 "is_public_sink": 0,1270 "destructive": 0,1271 "untrusted_content": 0,1272 "private_data": 01273 },1274 {1275 "is_public_sink": 0,1276 "destructive": 0,1277 "untrusted_content": 0,1278 "private_data": 01279 },1280 {1281 "is_public_sink": 0,1282 "destructive": 0,1283 "untrusted_content": 0,1284 "private_data": 01285 },1286 {1287 "is_public_sink": 0,1288 "destructive": 0,1289 "untrusted_content": 0,1290 "private_data": 01291 },1292 {1293 "is_public_sink": 0,1294 "destructive": 0,1295 "untrusted_content": 0,1296 "private_data": 01297 },1298 {1299 "is_public_sink": 0,1300 "destructive": 0,1301 "untrusted_content": 0,1302 "private_data": 01303 },1304 {1305 "is_public_sink": 0,1306 "destructive": 0,1307 "untrusted_content": 0,1308 "private_data": 01309 },1310 {1311 "is_public_sink": 0,1312 "destructive": 0,1313 "untrusted_content": 0,1314 "private_data": 01315 },1316 {1317 "is_public_sink": 0,1318 "destructive": 0,1319 "untrusted_content": 0,1320 "private_data": 01321 },1322 {1323 "is_public_sink": 0,1324 "destructive": 0,1325 "untrusted_content": 0,1326 "private_data": 01327 },1328 {1329 "is_public_sink": 0,1330 "destructive": 0,1331 "untrusted_content": 0,1332 "private_data": 01333 },1334 {1335 "is_public_sink": 0,1336 "destructive": 0,1337 "untrusted_content": 0,1338 "private_data": 01339 },1340 {1341 "is_public_sink": 0,1342 "destructive": 0,1343 "untrusted_content": 0,1344 "private_data": 01345 },1346 {1347 "is_public_sink": 0,1348 "destructive": 0,1349 "untrusted_content": 0,1350 "private_data": 01351 },1352 {1353 "is_public_sink": 0,1354 "destructive": 0,1355 "untrusted_content": 0,1356 "private_data": 01357 },1358 {1359 "is_public_sink": 0,1360 "destructive": 0,1361 "untrusted_content": 0,1362 "private_data": 01363 },1364 {1365 "is_public_sink": 0,1366 "destructive": 0,1367 "untrusted_content": 0,1368 "private_data": 01369 },1370 {1371 "is_public_sink": 0,1372 "destructive": 0,1373 "untrusted_content": 0,1374 "private_data": 01375 },1376 {1377 "is_public_sink": 0,1378 "destructive": 0,1379 "untrusted_content": 0,1380 "private_data": 01381 },1382 {1383 "is_public_sink": 0,1384 "destructive": 0,1385 "untrusted_content": 0,1386 "private_data": 01387 },1388 {1389 "is_public_sink": 0,1390 "destructive": 0,1391 "untrusted_content": 0,1392 "private_data": 01393 },1394 {1395 "is_public_sink": 0,1396 "destructive": 0,1397 "untrusted_content": 0,1398 "private_data": 01399 },1400 {1401 "is_public_sink": 0,1402 "destructive": 0,1403 "untrusted_content": 0,1404 "private_data": 01405 },1406 {1407 "is_public_sink": 0,1408 "destructive": 0,1409 "untrusted_content": 0,1410 "private_data": 01411 },1412 {1413 "is_public_sink": 0,1414 "destructive": 0,1415 "untrusted_content": 0,1416 "private_data": 01417 },1418 {1419 "is_public_sink": 0,1420 "destructive": 0,1421 "untrusted_content": 0,1422 "private_data": 01423 },1424 {1425 "is_public_sink": 0,1426 "destructive": 0,1427 "untrusted_content": 0,1428 "private_data": 01429 },1430 {1431 "is_public_sink": 0,1432 "destructive": 0,1433 "untrusted_content": 0,1434 "private_data": 01435 },1436 {1437 "is_public_sink": 0,1438 "destructive": 0,1439 "untrusted_content": 0,1440 "private_data": 01441 },1442 {1443 "is_public_sink": 0,1444 "destructive": 0,1445 "untrusted_content": 0,1446 "private_data": 01447 },1448 {1449 "is_public_sink": 0,1450 "destructive": 0,1451 "untrusted_content": 0,1452 "private_data": 01453 },1454 {1455 "is_public_sink": 0,1456 "destructive": 0,1457 "untrusted_content": 0,1458 "private_data": 01459 },1460 {1461 "is_public_sink": 0,1462 "destructive": 0,1463 "untrusted_content": 0,1464 "private_data": 01465 },1466 {1467 "is_public_sink": 0,1468 "destructive": 0,1469 "untrusted_content": 0,1470 "private_data": 01471 },1472 {1473 "is_public_sink": 0,1474 "destructive": 0,1475 "untrusted_content": 0,1476 "private_data": 01477 },1478 {1479 "is_public_sink": 0,1480 "destructive": 0,1481 "untrusted_content": 0,1482 "private_data": 01483 },1484 {1485 "is_public_sink": 0,1486 "destructive": 0,1487 "untrusted_content": 0,1488 "private_data": 01489 },1490 {1491 "is_public_sink": 0,1492 "destructive": 0,1493 "untrusted_content": 0,1494 "private_data": 01495 },1496 {1497 "is_public_sink": 0,1498 "destructive": 0,1499 "untrusted_content": 0,1500 "private_data": 01501 },1502 {1503 "is_public_sink": 0,1504 "destructive": 0,1505 "untrusted_content": 0,1506 "private_data": 01507 },1508 {1509 "is_public_sink": 0,1510 "destructive": 0,1511 "untrusted_content": 0,1512 "private_data": 01513 },1514 {1515 "is_public_sink": 0,1516 "destructive": 0,1517 "untrusted_content": 0,1518 "private_data": 01519 },1520 {1521 "is_public_sink": 0,1522 "destructive": 0,1523 "untrusted_content": 0,1524 "private_data": 01525 },1526 {1527 "is_public_sink": 0,1528 "destructive": 0,1529 "untrusted_content": 0,1530 "private_data": 01531 },1532 {1533 "is_public_sink": 0,1534 "destructive": 0,1535 "untrusted_content": 0,1536 "private_data": 01537 },1538 {1539 "is_public_sink": 0,1540 "destructive": 0,1541 "untrusted_content": 0,1542 "private_data": 01543 },1544 {1545 "is_public_sink": 0,1546 "destructive": 0,1547 "untrusted_content": 0,1548 "private_data": 01549 },1550 {1551 "is_public_sink": 0,1552 "destructive": 0,1553 "untrusted_content": 0,1554 "private_data": 01555 },1556 {1557 "is_public_sink": 0,1558 "destructive": 0,1559 "untrusted_content": 0,1560 "private_data": 01561 },1562 {1563 "is_public_sink": 0,1564 "destructive": 0,1565 "untrusted_content": 0,1566 "private_data": 01567 },1568 {1569 "is_public_sink": 0,1570 "destructive": 0,1571 "untrusted_content": 0,1572 "private_data": 01573 },1574 {1575 "is_public_sink": 0,1576 "destructive": 0,1577 "untrusted_content": 0,1578 "private_data": 01579 },1580 {1581 "is_public_sink": 0,1582 "destructive": 0,1583 "untrusted_content": 0,1584 "private_data": 01585 },1586 {1587 "is_public_sink": 0,1588 "destructive": 0,1589 "untrusted_content": 0,1590 "private_data": 01591 },1592 {1593 "is_public_sink": 0,1594 "destructive": 0,1595 "untrusted_content": 0,1596 "private_data": 01597 },1598 {1599 "is_public_sink": 0,1600 "destructive": 0,1601 "untrusted_content": 0,1602 "private_data": 01603 },1604 {1605 "is_public_sink": 0,1606 "destructive": 0,1607 "untrusted_content": 0,1608 "private_data": 01609 },1610 {1611 "is_public_sink": 0,1612 "destructive": 0,1613 "untrusted_content": 0,1614 "private_data": 01615 },1616 {1617 "is_public_sink": 0,1618 "destructive": 0,1619 "untrusted_content": 0,1620 "private_data": 01621 },1622 {1623 "is_public_sink": 0,1624 "destructive": 0,1625 "untrusted_content": 0,1626 "private_data": 01627 },1628 {1629 "is_public_sink": 0,1630 "destructive": 0,1631 "untrusted_content": 0,1632 "private_data": 01633 },1634 {1635 "is_public_sink": 0,1636 "destructive": 0,1637 "untrusted_content": 0,1638 "private_data": 01639 },1640 {1641 "is_public_sink": 0,1642 "destructive": 0,1643 "untrusted_content": 0,1644 "private_data": 01645 },1646 {1647 "is_public_sink": 0,1648 "destructive": 0,1649 "untrusted_content": 0,1650 "private_data": 01651 },1652 {1653 "is_public_sink": 0,1654 "destructive": 0,1655 "untrusted_content": 0,1656 "private_data": 01657 },1658 {1659 "is_public_sink": 0,1660 "destructive": 0,1661 "untrusted_content": 0,1662 "private_data": 01663 },1664 {1665 "is_public_sink": 0,1666 "destructive": 0,1667 "untrusted_content": 0,1668 "private_data": 01669 },1670 {1671 "is_public_sink": 0,1672 "destructive": 0,1673 "untrusted_content": 0,1674 "private_data": 01675 },1676 {1677 "is_public_sink": 0,1678 "destructive": 0,1679 "untrusted_content": 0,1680 "private_data": 01681 },1682 {1683 "is_public_sink": 0,1684 "destructive": 0,1685 "untrusted_content": 0,1686 "private_data": 01687 },1688 {1689 "is_public_sink": 0,1690 "destructive": 0,1691 "untrusted_content": 0,1692 "private_data": 01693 },1694 {1695 "is_public_sink": 0,1696 "destructive": 0,1697 "untrusted_content": 0,1698 "private_data": 01699 },1700 {1701 "is_public_sink": 0,1702 "destructive": 0,1703 "untrusted_content": 0,1704 "private_data": 01705 },1706 {1707 "is_public_sink": 0,1708 "destructive": 0,1709 "untrusted_content": 0,1710 "private_data": 01711 },1712 {1713 "is_public_sink": 0,1714 "destructive": 0,1715 "untrusted_content": 0,1716 "private_data": 01717 },1718 {1719 "is_public_sink": 0,1720 "destructive": 0,1721 "untrusted_content": 0,1722 "private_data": 01723 },1724 {1725 "is_public_sink": 0,1726 "destructive": 0,1727 "untrusted_content": 0,1728 "private_data": 01729 },1730 {1731 "is_public_sink": 0,1732 "destructive": 0,1733 "untrusted_content": 0,1734 "private_data": 01735 },1736 {1737 "is_public_sink": 0,1738 "destructive": 0,1739 "untrusted_content": 0,1740 "private_data": 01741 },1742 {1743 "is_public_sink": 0,1744 "destructive": 0,1745 "untrusted_content": 0,1746 "private_data": 01747 },1748 {1749 "is_public_sink": 0,1750 "destructive": 0,1751 "untrusted_content": 0,1752 "private_data": 01753 },1754 {1755 "is_public_sink": 0,1756 "destructive": 0,1757 "untrusted_content": 0,1758 "private_data": 01759 },1760 {1761 "is_public_sink": 0,1762 "destructive": 0,1763 "untrusted_content": 0,1764 "private_data": 01765 },1766 {1767 "is_public_sink": 0,1768 "destructive": 0,1769 "untrusted_content": 0,1770 "private_data": 01771 },1772 {1773 "is_public_sink": 0,1774 "destructive": 0,1775 "untrusted_content": 0,1776 "private_data": 01777 },1778 {1779 "is_public_sink": 0,1780 "destructive": 0,1781 "untrusted_content": 0,1782 "private_data": 01783 },1784 {1785 "is_public_sink": 0,1786 "destructive": 0,1787 "untrusted_content": 0,1788 "private_data": 01789 },1790 {1791 "is_public_sink": 0,1792 "destructive": 0,1793 "untrusted_content": 0,1794 "private_data": 01795 },1796 {1797 "is_public_sink": 0,1798 "destructive": 0,1799 "untrusted_content": 0,1800 "private_data": 01801 },1802 {1803 "is_public_sink": 0,1804 "destructive": 0,1805 "untrusted_content": 0,1806 "private_data": 01807 },1808 {1809 "is_public_sink": 0,1810 "destructive": 0,1811 "untrusted_content": 0,1812 "private_data": 01813 },1814 {1815 "is_public_sink": 0,1816 "destructive": 0,1817 "untrusted_content": 0,1818 "private_data": 01819 },1820 {1821 "is_public_sink": 0,1822 "destructive": 0,1823 "untrusted_content": 0,1824 "private_data": 01825 },1826 {1827 "is_public_sink": 0,1828 "destructive": 0,1829 "untrusted_content": 0,1830 "private_data": 01831 },1832 {1833 "is_public_sink": 0,1834 "destructive": 0,1835 "untrusted_content": 0,1836 "private_data": 01837 },1838 {1839 "is_public_sink": 0,1840 "destructive": 0,1841 "untrusted_content": 0,1842 "private_data": 01843 },1844 {1845 "is_public_sink": 0,1846 "destructive": 0,1847 "untrusted_content": 0,1848 "private_data": 01849 },1850 {1851 "is_public_sink": 0,1852 "destructive": 0,1853 "untrusted_content": 0,1854 "private_data": 01855 },1856 {1857 "is_public_sink": 0,1858 "destructive": 0,1859 "untrusted_content": 0,1860 "private_data": 01861 }1862 ]1863 ],1864 "error": null1865 }1866}18671868Process exited with code 01869✓ Completed in 165276ms
npm-audit▸11 findings164768ms
View logs
1[2026-02-13T00:36:44.886Z] $ npm audit --json --prefix /tmp/clawguard-scan-lE2FSJ/repo/skills/pin-alt/2026-02-10-clawhub-clawvault-1-5-12{3 "auditReportVersion": 2,4 "vulnerabilities": {5 "@modelcontextprotocol/sdk": {6 "name": "@modelcontextprotocol/sdk",7 "severity": "high",8 "isDirect": false,9 "via": [10 {11 "source": 1113080,12 "name": "@modelcontextprotocol/sdk",13 "dependency": "@modelcontextprotocol/sdk",14 "title": "@modelcontextprotocol/sdk has cross-client data leak via shared server/transport instance reuse",15 "url": "https://github.com/advisories/GHSA-345p-7cg4-v4c7",16 "severity": "high",17 "cwe": [18 "CWE-362"19 ],20 "cvss": {21 "score": 7.1,22 "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N"23 },24 "range": ">=1.10.0 <=1.25.3"25 }26 ],27 "effects": [],28 "range": "1.10.0 - 1.25.3",29 "nodes": [30 "node_modules/@modelcontextprotocol/sdk"31 ],32 "fixAvailable": true33 },34 "axios": {35 "name": "axios",36 "severity": "high",37 "isDirect": false,38 "via": [39 {40 "source": 1113092,41 "name": "axios",42 "dependency": "axios",43 "title": "Axios is Vulnerable to Denial of Service via __proto__ Key in mergeConfig",44 "url": "https://github.com/advisories/GHSA-43fc-jf86-j433",45 "severity": "high",46 "cwe": [47 "CWE-754"48 ],49 "cvss": {50 "score": 7.5,51 "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"52 },53 "range": "<=1.13.4"54 }55 ],56 "effects": [],57 "range": "<=1.13.4",58 "nodes": [59 "node_modules/axios"60 ],61 "fixAvailable": true62 },63 "cmake-js": {64 "name": "cmake-js",65 "severity": "high",66 "isDirect": false,67 "via": [68 "tar"69 ],70 "effects": [71 "node-llama-cpp"72 ],73 "range": "<=7.4.0",74 "nodes": [75 "node_modules/cmake-js"76 ],77 "fixAvailable": true78 },79 "esbuild": {80 "name": "esbuild",81 "severity": "moderate",82 "isDirect": false,83 "via": [84 {85 "source": 1102341,86 "name": "esbuild",87 "dependency": "esbuild",88 "title": "esbuild enables any website to send any requests to the development server and read the response",89 "url": "https://github.com/advisories/GHSA-67mh-4wv8-2f99",90 "severity": "moderate",91 "cwe": [92 "CWE-346"93 ],94 "cvss": {95 "score": 5.3,96 "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N"97 },98 "range": "<=0.24.2"99 }100 ],101 "effects": [102 "vite"103 ],104 "range": "<=0.24.2",105 "nodes": [106 "node_modules/vite/node_modules/esbuild"107 ],108 "fixAvailable": {109 "name": "vitest",110 "version": "4.0.18",111 "isSemVerMajor": true112 }113 },114 "node-llama-cpp": {115 "name": "node-llama-cpp",116 "severity": "high",117 "isDirect": false,118 "via": [119 "cmake-js"120 ],121 "effects": [122 "qmd"123 ],124 "range": ">=2.4.0",125 "nodes": [126 "node_modules/node-llama-cpp"127 ],128 "fixAvailable": true129 },130 "qmd": {131 "name": "qmd",132 "severity": "high",133 "isDirect": true,134 "via": [135 "node-llama-cpp"136 ],137 "effects": [],138 "range": "",139 "nodes": [140 "node_modules/qmd"141 ],142 "fixAvailable": true143 },144 "qs": {145 "name": "qs",146 "severity": "low",147 "isDirect": false,148 "via": [149 {150 "source": 1113161,151 "name": "qs",152 "dependency": "qs",153 "title": "qs's arrayLimit bypass in comma parsing allows denial of service",154 "url": "https://github.com/advisories/GHSA-w7fw-mjwx-w883",155 "severity": "low",156 "cwe": [157 "CWE-20"158 ],159 "cvss": {160 "score": 3.7,161 "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L"162 },163 "range": ">=6.7.0 <=6.14.1"164 }165 ],166 "effects": [],167 "range": "6.7.0 - 6.14.1",168 "nodes": [169 "node_modules/qs"170 ],171 "fixAvailable": true172 },173 "tar": {174 "name": "tar",175 "severity": "high",176 "isDirect": false,177 "via": [178 {179 "source": 1112255,180 "name": "tar",181 "dependency": "tar",182 "title": "node-tar is Vulnerable to Arbitrary File Overwrite and Symlink Poisoning via Insufficient Path Sanitization",183 "url": "https://github.com/advisories/GHSA-8qq5-rm4j-mr97",184 "severity": "high",185 "cwe": [186 "CWE-22"187 ],188 "cvss": {189 "score": 0,190 "vectorString": null191 },192 "range": "<=7.5.2"193 },194 {195 "source": 1112329,196 "name": "tar",197 "dependency": "tar",198 "title": "Race Condition in node-tar Path Reservations via Unicode Ligature Collisions on macOS APFS",199 "url": "https://github.com/advisories/GHSA-r6q2-hw4h-h46w",200 "severity": "high",201 "cwe": [202 "CWE-176"203 ],204 "cvss": {205 "score": 8.8,206 "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L"207 },208 "range": "<=7.5.3"209 },210 {211 "source": 1112659,212 "name": "tar",213 "dependency": "tar",214 "title": "node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Traversal",215 "url": "https://github.com/advisories/GHSA-34x7-hfp2-rc4v",216 "severity": "high",217 "cwe": [218 "CWE-22",219 "CWE-59"220 ],221 "cvss": {222 "score": 8.2,223 "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N"224 },225 "range": "<7.5.7"226 }227 ],228 "effects": [229 "cmake-js"230 ],231 "range": "<=7.5.6",232 "nodes": [233 "node_modules/tar"234 ],235 "fixAvailable": true236 },237 "vite": {238 "name": "vite",239 "severity": "moderate",240 "isDirect": false,241 "via": [242 "esbuild"243 ],244 "effects": [245 "vite-node",246 "vitest"247 ],248 "range": "0.11.0 - 6.1.6",249 "nodes": [250 "node_modules/vite"251 ],252 "fixAvailable": {253 "name": "vitest",254 "version": "4.0.18",255 "isSemVerMajor": true256 }257 },258 "vite-node": {259 "name": "vite-node",260 "severity": "moderate",261 "isDirect": false,262 "via": [263 "vite"264 ],265 "effects": [266 "vitest"267 ],268 "range": "<=2.2.0-beta.2",269 "nodes": [270 "node_modules/vite-node"271 ],272 "fixAvailable": {273 "name": "vitest",274 "version": "4.0.18",275 "isSemVerMajor": true276 }277 },278 "vitest": {279 "name": "vitest",280 "severity": "moderate",281 "isDirect": true,282 "via": [283 "vite",284 "vite-node"285 ],286 "effects": [],287 "range": "0.0.1 - 0.0.12 || 0.0.29 - 0.0.122 || 0.3.3 - 2.2.0-beta.2",288 "nodes": [289 "node_modules/vitest"290 ],291 "fixAvailable": {292 "name": "vitest",293 "version": "4.0.18",294 "isSemVerMajor": true295 }296 }297 },298 "metadata": {299 "vulnerabilities": {300 "info": 0,301 "low": 1,302 "moderate": 4,303 "high": 6,304 "critical": 0,305 "total": 11306 },307 "dependencies": {308 "prod": 109,309 "dev": 173,310 "optional": 355,311 "peer": 278,312 "peerOptional": 0,313 "total": 561314 }315 }316}317318Process exited with code 1319✓ Completed in 164768ms
Scanned: 2/13/2026, 12:37:36 AM