abtars 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +84 -0
- package/bundle/_registry.generated-M4WY2MMI.js +35 -0
- package/bundle/_registry.generated-M4WY2MMI.js.map +7 -0
- package/bundle/abtars-browser.js +162 -0
- package/bundle/abtars-browser.js.map +7 -0
- package/bundle/abtars-cli.js +1438 -0
- package/bundle/abtars-cli.js.map +7 -0
- package/bundle/abtars-restart.js +12 -0
- package/bundle/abtars-restart.js.map +7 -0
- package/bundle/abtars-rss.js +165 -0
- package/bundle/abtars-rss.js.map +7 -0
- package/bundle/abtars-task.js +258 -0
- package/bundle/abtars-task.js.map +7 -0
- package/bundle/abtars.js +4072 -0
- package/bundle/abtars.js.map +7 -0
- package/bundle/agent-api-rate-limit-OQNFMXTZ.js +38 -0
- package/bundle/agent-api-rate-limit-OQNFMXTZ.js.map +7 -0
- package/bundle/agent-registry-LT4JNQH6.js +18 -0
- package/bundle/agent-registry-LT4JNQH6.js.map +7 -0
- package/bundle/agents/default.md +29 -0
- package/bundle/anthropic-adapter-2APTH3LA.js +40 -0
- package/bundle/anthropic-adapter-2APTH3LA.js.map +7 -0
- package/bundle/bridge-lock-transport-4AC2G5G6.js +39 -0
- package/bundle/bridge-lock-transport-4AC2G5G6.js.map +7 -0
- package/bundle/browse-delivery-JXBY36GK.js +17 -0
- package/bundle/browse-delivery-JXBY36GK.js.map +7 -0
- package/bundle/browser-ELNDVPLC.js +18 -0
- package/bundle/browser-ELNDVPLC.js.map +7 -0
- package/bundle/capability-CIL3G4FI.js +17 -0
- package/bundle/capability-CIL3G4FI.js.map +7 -0
- package/bundle/chunk-265TPOPC.js +289 -0
- package/bundle/chunk-265TPOPC.js.map +7 -0
- package/bundle/chunk-2UENBO6M.js +223 -0
- package/bundle/chunk-2UENBO6M.js.map +7 -0
- package/bundle/chunk-2UPU3OW6.js +67 -0
- package/bundle/chunk-2UPU3OW6.js.map +7 -0
- package/bundle/chunk-2XU2X4OI.js +125 -0
- package/bundle/chunk-2XU2X4OI.js.map +7 -0
- package/bundle/chunk-3B7BBE4F.js +758 -0
- package/bundle/chunk-3B7BBE4F.js.map +7 -0
- package/bundle/chunk-3E545J66.js +69 -0
- package/bundle/chunk-3E545J66.js.map +7 -0
- package/bundle/chunk-5R2ANXQ7.js +510 -0
- package/bundle/chunk-5R2ANXQ7.js.map +7 -0
- package/bundle/chunk-6CPN4IGS.js +507 -0
- package/bundle/chunk-6CPN4IGS.js.map +7 -0
- package/bundle/chunk-6NR3OHEW.js +88 -0
- package/bundle/chunk-6NR3OHEW.js.map +7 -0
- package/bundle/chunk-6SETMHNN.js +206 -0
- package/bundle/chunk-6SETMHNN.js.map +7 -0
- package/bundle/chunk-6UCRKRWR.js +644 -0
- package/bundle/chunk-6UCRKRWR.js.map +7 -0
- package/bundle/chunk-AR6GO6YC.js +83 -0
- package/bundle/chunk-AR6GO6YC.js.map +7 -0
- package/bundle/chunk-AZJIODTQ.js +54 -0
- package/bundle/chunk-AZJIODTQ.js.map +7 -0
- package/bundle/chunk-BHMZ4RCC.js +3706 -0
- package/bundle/chunk-BHMZ4RCC.js.map +7 -0
- package/bundle/chunk-BQ2L4GMG.js +9175 -0
- package/bundle/chunk-BQ2L4GMG.js.map +7 -0
- package/bundle/chunk-BSSBCSCL.js +159 -0
- package/bundle/chunk-BSSBCSCL.js.map +7 -0
- package/bundle/chunk-BUUVFUPO.js +157 -0
- package/bundle/chunk-BUUVFUPO.js.map +7 -0
- package/bundle/chunk-CEVRHKJY.js +131 -0
- package/bundle/chunk-CEVRHKJY.js.map +7 -0
- package/bundle/chunk-CWOHNFUV.js +39 -0
- package/bundle/chunk-CWOHNFUV.js.map +7 -0
- package/bundle/chunk-D2DCBO6M.js +228 -0
- package/bundle/chunk-D2DCBO6M.js.map +7 -0
- package/bundle/chunk-FMWKEPM7.js +31 -0
- package/bundle/chunk-FMWKEPM7.js.map +7 -0
- package/bundle/chunk-GRNENTPA.js +145 -0
- package/bundle/chunk-GRNENTPA.js.map +7 -0
- package/bundle/chunk-GST5T3WZ.js +93 -0
- package/bundle/chunk-GST5T3WZ.js.map +7 -0
- package/bundle/chunk-GUQVJC3U.js +299 -0
- package/bundle/chunk-GUQVJC3U.js.map +7 -0
- package/bundle/chunk-HX7Y7EYP.js +3659 -0
- package/bundle/chunk-HX7Y7EYP.js.map +7 -0
- package/bundle/chunk-JCJS4ZIB.js +296 -0
- package/bundle/chunk-JCJS4ZIB.js.map +7 -0
- package/bundle/chunk-JW6RU47G.js +184 -0
- package/bundle/chunk-JW6RU47G.js.map +7 -0
- package/bundle/chunk-LSPKJQCI.js +24 -0
- package/bundle/chunk-LSPKJQCI.js.map +7 -0
- package/bundle/chunk-M6VBAPNT.js +16 -0
- package/bundle/chunk-M6VBAPNT.js.map +7 -0
- package/bundle/chunk-MPX525QO.js +129 -0
- package/bundle/chunk-MPX525QO.js.map +7 -0
- package/bundle/chunk-MW6WDLU7.js +130 -0
- package/bundle/chunk-MW6WDLU7.js.map +7 -0
- package/bundle/chunk-NT3OBORC.js +215 -0
- package/bundle/chunk-NT3OBORC.js.map +7 -0
- package/bundle/chunk-NWDBD4PA.js +50 -0
- package/bundle/chunk-NWDBD4PA.js.map +7 -0
- package/bundle/chunk-OP7BTAWY.js +29 -0
- package/bundle/chunk-OP7BTAWY.js.map +7 -0
- package/bundle/chunk-PLCY3GFH.js +77 -0
- package/bundle/chunk-PLCY3GFH.js.map +7 -0
- package/bundle/chunk-PNEDC45Y.js +97 -0
- package/bundle/chunk-PNEDC45Y.js.map +7 -0
- package/bundle/chunk-QBGBT5QS.js +81 -0
- package/bundle/chunk-QBGBT5QS.js.map +7 -0
- package/bundle/chunk-RVE2N7FA.js +70 -0
- package/bundle/chunk-RVE2N7FA.js.map +7 -0
- package/bundle/chunk-TZHIDLDS.js +71910 -0
- package/bundle/chunk-TZHIDLDS.js.map +7 -0
- package/bundle/chunk-UCQ2WC3B.js +126 -0
- package/bundle/chunk-UCQ2WC3B.js.map +7 -0
- package/bundle/chunk-UHRP745J.js +214 -0
- package/bundle/chunk-UHRP745J.js.map +7 -0
- package/bundle/chunk-V76TVMCM.js +58 -0
- package/bundle/chunk-V76TVMCM.js.map +7 -0
- package/bundle/chunk-VVEDVGCR.js +981 -0
- package/bundle/chunk-VVEDVGCR.js.map +7 -0
- package/bundle/chunk-W6FAL35D.js +102 -0
- package/bundle/chunk-W6FAL35D.js.map +7 -0
- package/bundle/chunk-X6TERNVJ.js +15902 -0
- package/bundle/chunk-X6TERNVJ.js.map +7 -0
- package/bundle/chunk-X76UX47U.js +47 -0
- package/bundle/chunk-X76UX47U.js.map +7 -0
- package/bundle/chunk-XREWVCUO.js +518 -0
- package/bundle/chunk-XREWVCUO.js.map +7 -0
- package/bundle/chunk-Y6XAEX2Q.js +408 -0
- package/bundle/chunk-Y6XAEX2Q.js.map +7 -0
- package/bundle/chunk-YOCTDKKL.js +28 -0
- package/bundle/chunk-YOCTDKKL.js.map +7 -0
- package/bundle/chunk-ZXPXCDA6.js +160 -0
- package/bundle/chunk-ZXPXCDA6.js.map +7 -0
- package/bundle/commands-BHVUOU3V.js +31 -0
- package/bundle/commands-BHVUOU3V.js.map +7 -0
- package/bundle/completion-buffer-P253ONKF.js +13 -0
- package/bundle/completion-buffer-P253ONKF.js.map +7 -0
- package/bundle/config-RGSDAPZN.js +19 -0
- package/bundle/config-RGSDAPZN.js.map +7 -0
- package/bundle/config-show-ERTATR6E.js +40 -0
- package/bundle/config-show-ERTATR6E.js.map +7 -0
- package/bundle/context-HCEGZNDC.js +72 -0
- package/bundle/context-HCEGZNDC.js.map +7 -0
- package/bundle/delegation-tools-GYTS2D6A.js +27 -0
- package/bundle/delegation-tools-GYTS2D6A.js.map +7 -0
- package/bundle/deploy-lib-import-32ZFKHWP.js +49 -0
- package/bundle/deploy-lib-import-32ZFKHWP.js.map +7 -0
- package/bundle/digital-signature-OFCGSHWO.js +13 -0
- package/bundle/digital-signature-OFCGSHWO.js.map +7 -0
- package/bundle/direct-api-transport-YR7SXXNN.js +860 -0
- package/bundle/direct-api-transport-YR7SXXNN.js.map +7 -0
- package/bundle/discord-adapter-YYWVMPPU.js +584 -0
- package/bundle/discord-adapter-YYWVMPPU.js.map +7 -0
- package/bundle/dist-MTMKARCP.js +1969 -0
- package/bundle/dist-MTMKARCP.js.map +7 -0
- package/bundle/dns-wakeup-27M7D2MR.js +107 -0
- package/bundle/dns-wakeup-27M7D2MR.js.map +7 -0
- package/bundle/doctor-QNUSDY73.js +248 -0
- package/bundle/doctor-QNUSDY73.js.map +7 -0
- package/bundle/ensure-invariants-NMXNS476.js +49 -0
- package/bundle/ensure-invariants-NMXNS476.js.map +7 -0
- package/bundle/env-schema-2KBHBDGN.js +19 -0
- package/bundle/env-schema-2KBHBDGN.js.map +7 -0
- package/bundle/esm-DDP6NCZG.js +100663 -0
- package/bundle/esm-DDP6NCZG.js.map +7 -0
- package/bundle/fallback-policy-L4QV2PEJ.js +46 -0
- package/bundle/fallback-policy-L4QV2PEJ.js.map +7 -0
- package/bundle/health-check-SPA7NT6N.js +56 -0
- package/bundle/health-check-SPA7NT6N.js.map +7 -0
- package/bundle/hook-system-6Q5YTR53.js +17 -0
- package/bundle/hook-system-6Q5YTR53.js.map +7 -0
- package/bundle/hotskills-K7BM4YLB.js +12 -0
- package/bundle/hotskills-K7BM4YLB.js.map +7 -0
- package/bundle/install-6HRZVKUM.js +15 -0
- package/bundle/install-6HRZVKUM.js.map +7 -0
- package/bundle/install-log-IAPHYKD4.js +28 -0
- package/bundle/install-log-IAPHYKD4.js.map +7 -0
- package/bundle/install-manifest-SPQRUNXL.js +102 -0
- package/bundle/install-manifest-SPQRUNXL.js.map +7 -0
- package/bundle/install-validate-PVLZXYLQ.js +53 -0
- package/bundle/install-validate-PVLZXYLQ.js.map +7 -0
- package/bundle/irc-adapter-OI5UZSQF.js +293 -0
- package/bundle/irc-adapter-OI5UZSQF.js.map +7 -0
- package/bundle/irc-config-55YO6EGB.js +88 -0
- package/bundle/irc-config-55YO6EGB.js.map +7 -0
- package/bundle/logs-ZNYXX5PA.js +19 -0
- package/bundle/logs-ZNYXX5PA.js.map +7 -0
- package/bundle/media-utils-XNNDTYFI.js +4662 -0
- package/bundle/media-utils-XNNDTYFI.js.map +7 -0
- package/bundle/message-pipeline-LLH5SYMO.js +33 -0
- package/bundle/message-pipeline-LLH5SYMO.js.map +7 -0
- package/bundle/meta.json +41304 -0
- package/bundle/model-health-registry-35LQNVQR.js +11 -0
- package/bundle/model-health-registry-35LQNVQR.js.map +7 -0
- package/bundle/notification-Y5S5MMLV.js +13 -0
- package/bundle/notification-Y5S5MMLV.js.map +7 -0
- package/bundle/openrouter-credits-EDY7ETAU.js +32 -0
- package/bundle/openrouter-credits-EDY7ETAU.js.map +7 -0
- package/bundle/passwd-RRFV4CC5.js +133 -0
- package/bundle/passwd-RRFV4CC5.js.map +7 -0
- package/bundle/paths-G33RZWZ7.js +17 -0
- package/bundle/paths-G33RZWZ7.js.map +7 -0
- package/bundle/peer-client-52XYMNI7.js +156 -0
- package/bundle/peer-client-52XYMNI7.js.map +7 -0
- package/bundle/peer-config-VK6EDLN5.js +16 -0
- package/bundle/peer-config-VK6EDLN5.js.map +7 -0
- package/bundle/peer-sessions-EAXTNQ36.js +49 -0
- package/bundle/peer-sessions-EAXTNQ36.js.map +7 -0
- package/bundle/pending-callback-RIMQZ7FJ.js +40 -0
- package/bundle/pending-callback-RIMQZ7FJ.js.map +7 -0
- package/bundle/phase-transport-KYERDL2O.js +22 -0
- package/bundle/phase-transport-KYERDL2O.js.map +7 -0
- package/bundle/public/css/dashboard.css +542 -0
- package/bundle/public/index.html +180 -0
- package/bundle/public/js/app.js +437 -0
- package/bundle/public/memory-universe.js +384 -0
- package/bundle/responses-adapter-AAQTY3K4.js +30 -0
- package/bundle/responses-adapter-AAQTY3K4.js.map +7 -0
- package/bundle/restore-ZE3SEPSS.js +46 -0
- package/bundle/restore-ZE3SEPSS.js.map +7 -0
- package/bundle/self-healer-utils-DMUUXC47.js +43 -0
- package/bundle/self-healer-utils-DMUUXC47.js.map +7 -0
- package/bundle/skill-stats-LLEXEXLR.js +22 -0
- package/bundle/skill-stats-LLEXEXLR.js.map +7 -0
- package/bundle/sleep-OYIUOVQD.js +19 -0
- package/bundle/sleep-OYIUOVQD.js.map +7 -0
- package/bundle/soul-loader-54WCVNLJ.js +16 -0
- package/bundle/soul-loader-54WCVNLJ.js.map +7 -0
- package/bundle/src-JL4PVO23.js +8 -0
- package/bundle/src-JL4PVO23.js.map +7 -0
- package/bundle/sse-parser-anthropic-P7CE2MH2.js +72 -0
- package/bundle/sse-parser-anthropic-P7CE2MH2.js.map +7 -0
- package/bundle/sse-parser-responses-EQQA5FWN.js +63 -0
- package/bundle/sse-parser-responses-EQQA5FWN.js.map +7 -0
- package/bundle/ssrf-guard-FZCBYIVW.js +64 -0
- package/bundle/ssrf-guard-FZCBYIVW.js.map +7 -0
- package/bundle/start-FH3GRMJ4.js +35 -0
- package/bundle/start-FH3GRMJ4.js.map +7 -0
- package/bundle/stream-single-WSG4D53C.js +33 -0
- package/bundle/stream-single-WSG4D53C.js.map +7 -0
- package/bundle/stt-2UH3RITX.js +14 -0
- package/bundle/stt-2UH3RITX.js.map +7 -0
- package/bundle/subagent-runtime-LE2ZXH3G.js +12 -0
- package/bundle/subagent-runtime-LE2ZXH3G.js.map +7 -0
- package/bundle/system-message-T5R3EYYN.js +30 -0
- package/bundle/system-message-T5R3EYYN.js.map +7 -0
- package/bundle/system-status-KQ6KHFJ6.js +189 -0
- package/bundle/system-status-KQ6KHFJ6.js.map +7 -0
- package/bundle/task-store-K7CQDEPI.js +22 -0
- package/bundle/task-store-K7CQDEPI.js.map +7 -0
- package/bundle/telegram-adapter-2V3XUMT5.js +1060 -0
- package/bundle/telegram-adapter-2V3XUMT5.js.map +7 -0
- package/bundle/tool-registry-MU3OX4UI.js +38 -0
- package/bundle/tool-registry-MU3OX4UI.js.map +7 -0
- package/bundle/tool-sandbox-VYOK4ZOA.js +20 -0
- package/bundle/tool-sandbox-VYOK4ZOA.js.map +7 -0
- package/bundle/transport-config-YLXU33RO.js +57 -0
- package/bundle/transport-config-YLXU33RO.js.map +7 -0
- package/bundle/update-QCW5LXRN.js +13 -0
- package/bundle/update-QCW5LXRN.js.map +7 -0
- package/bundle/update-check-27KZSAP6.js +12 -0
- package/bundle/update-check-27KZSAP6.js.map +7 -0
- package/bundle/usage-tracker-OVVEVMOY.js +17 -0
- package/bundle/usage-tracker-OVVEVMOY.js.map +7 -0
- package/bundle/user-registry-D4SD73UV.js +16 -0
- package/bundle/user-registry-D4SD73UV.js.map +7 -0
- package/core/professor.json +14 -0
- package/core/prompts/browsing_prompt.md +39 -0
- package/core/prompts/compaction.md +32 -0
- package/core/skills/memory/classification/SKILL.md +37 -0
- package/core/skills/memory/memory-anomalies/SKILL.md +39 -0
- package/core/skills/memory/memory-search/SKILL.md +48 -0
- package/core/skills/memory/topic-save/SKILL.md +44 -0
- package/core/skills/ops/cron/SKILL.md +51 -0
- package/core/skills/ops/gdrive-backup/SKILL.md +15 -0
- package/core/skills/ops/session-start/SKILL.md +11 -0
- package/core/skills/ops/skill-authoring/SKILL.md +54 -0
- package/core/skills/ops/system-health/SKILL.md +104 -0
- package/core/skills/ops/troubleshooting/SKILL.md +48 -0
- package/core/skills/ops/trust-gating/SKILL.md +30 -0
- package/core/skills/tools/a2a-communication/SKILL.md +68 -0
- package/core/skills/tools/browse-delegate/SKILL.md +27 -0
- package/core/skills/tools/browser/SKILL.md +36 -0
- package/core/skills/tools/clawhub/SKILL.md +44 -0
- package/core/skills/tools/delegation/SKILL.md +48 -0
- package/core/skills/tools/fxtwitter/SKILL.md +52 -0
- package/core/skills/tools/gmail/SKILL.md +44 -0
- package/core/skills/tools/irc-chat/SKILL.md +84 -0
- package/core/skills/tools/linear/SKILL.md +90 -0
- package/core/skills/tools/mcporter/SKILL.md +46 -0
- package/core/skills/tools/model-scout/SKILL.md +132 -0
- package/core/skills/tools/model-scout/scout-add-model.py +67 -0
- package/core/skills/tools/model-scout/scout-ollama.py +116 -0
- package/core/skills/tools/model-scout/scout-openrouter.py +85 -0
- package/core/skills/tools/nlm/SKILL.md +40 -0
- package/core/skills/tools/todo/SKILL.md +30 -0
- package/core/skills/tools/twitterX/SKILL.md +52 -0
- package/core/skills/tools/twitterX/scripts/abtars-tweet.js +532 -0
- package/core/skills/tools/twitterX/scripts/package.json +1 -0
- package/core/skills/tools/web-fetch/SKILL.md +29 -0
- package/package.json +59 -0
- package/scripts/abtars-daemon.service +23 -0
- package/scripts/abtars-fetch.sh +42 -0
- package/scripts/abtars-watchdog.service +13 -0
- package/scripts/abtars.sh +14 -0
- package/scripts/abtars@.service +21 -0
- package/scripts/browser-patchright.sh +79 -0
- package/scripts/com.abtars.daemon.plist +24 -0
- package/scripts/com.abtars.watchdog.plist +27 -0
- package/scripts/daily-backup.sh +62 -0
- package/scripts/doctor.sh +553 -0
- package/scripts/hooks/audit-logger.sh +22 -0
- package/scripts/upgrade-deps.sh +64 -0
- package/scripts/watchdog.sh +309 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __chunk_filename = __bundleFileURLToPath(import.meta.url); const __chunk_dirname = __bundleDirname(__chunk_filename);
|
|
2
|
+
import {
|
|
3
|
+
init_log_and_swallow,
|
|
4
|
+
logAndSwallow
|
|
5
|
+
} from "./chunk-FMWKEPM7.js";
|
|
6
|
+
import {
|
|
7
|
+
init_logger,
|
|
8
|
+
logInfo,
|
|
9
|
+
logWarn
|
|
10
|
+
} from "./chunk-BUUVFUPO.js";
|
|
11
|
+
import {
|
|
12
|
+
abtarsHome,
|
|
13
|
+
init_paths
|
|
14
|
+
} from "./chunk-X76UX47U.js";
|
|
15
|
+
import {
|
|
16
|
+
__export,
|
|
17
|
+
__require
|
|
18
|
+
} from "./chunk-NWDBD4PA.js";
|
|
19
|
+
|
|
20
|
+
// src/capabilities/hotskills/index.ts
|
|
21
|
+
var hotskills_exports = {};
|
|
22
|
+
__export(hotskills_exports, {
|
|
23
|
+
register: () => register
|
|
24
|
+
});
|
|
25
|
+
import { join as join2 } from "node:path";
|
|
26
|
+
|
|
27
|
+
// src/components/skill-watcher.ts
|
|
28
|
+
init_log_and_swallow();
|
|
29
|
+
init_logger();
|
|
30
|
+
import { readdirSync, readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
31
|
+
import { join, basename, dirname, resolve } from "node:path";
|
|
32
|
+
import { execFileSync } from "node:child_process";
|
|
33
|
+
import { homedir } from "node:os";
|
|
34
|
+
var TAG = "skill-reloader";
|
|
35
|
+
var SkillWatcher = class {
|
|
36
|
+
constructor(skillsDir, catalogPath) {
|
|
37
|
+
this.skillsDir = skillsDir;
|
|
38
|
+
this.catalogPath = catalogPath;
|
|
39
|
+
}
|
|
40
|
+
/** Per-instance cache of `which <bin>` results. Avoids repeated execFileSync on heartbeat ticks (#369). */
|
|
41
|
+
binaryCache = /* @__PURE__ */ new Map();
|
|
42
|
+
/** Generate skills_catalog.md from all skill files. Called on startup + when skills change. */
|
|
43
|
+
generateCatalog() {
|
|
44
|
+
const files = this.scanMdFiles(this.skillsDir);
|
|
45
|
+
const entries = [];
|
|
46
|
+
const skipped = [];
|
|
47
|
+
const skillsCfg = this.loadSkillsConfig();
|
|
48
|
+
for (const filepath of files) {
|
|
49
|
+
const header = this.parseSkillHeader(filepath);
|
|
50
|
+
if (!header.name) continue;
|
|
51
|
+
if (header.primaryEnv && !process.env[header.primaryEnv]) {
|
|
52
|
+
const entry2 = skillsCfg.entries?.[header.name];
|
|
53
|
+
if (entry2?.apiKey) process.env[header.primaryEnv] = entry2.apiKey;
|
|
54
|
+
}
|
|
55
|
+
const entry = skillsCfg.entries?.[header.name];
|
|
56
|
+
if (entry?.env) {
|
|
57
|
+
for (const [k, v] of Object.entries(entry.env)) {
|
|
58
|
+
if (!process.env[k]) process.env[k] = v;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (header.requires) {
|
|
62
|
+
const { eligible, missing } = this.checkEligibility(header.requires);
|
|
63
|
+
if (!eligible) {
|
|
64
|
+
skipped.push(`${header.name} (missing: ${missing.join(", ")})`);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
entries.push(`- [${this.getSourceDir(filepath)}] ${header.name}: ${header.description}`);
|
|
69
|
+
}
|
|
70
|
+
const guidance = [
|
|
71
|
+
"",
|
|
72
|
+
"## Skill maintenance",
|
|
73
|
+
"- If you solved something non-trivial (multi-step, error-prone, or likely to recur), save it as a skill with skill_create.",
|
|
74
|
+
"- If a skill you just used was wrong or incomplete, fix it with skill_patch before moving on.",
|
|
75
|
+
""
|
|
76
|
+
].join("\n");
|
|
77
|
+
const content = `# Skills Catalog
|
|
78
|
+
|
|
79
|
+
When a user request matches a skill below, read its SKILL.md at ~/.abtars/skills/<dir>/SKILL.md for detailed instructions before acting.
|
|
80
|
+
|
|
81
|
+
${entries.join("\n")}
|
|
82
|
+
${guidance}`;
|
|
83
|
+
try {
|
|
84
|
+
writeFileSync(this.catalogPath, content, "utf-8");
|
|
85
|
+
const skippedStr = skipped.length > 0 ? `, ${skipped.length} skipped \u2014 ${skipped.join(", ")}` : "";
|
|
86
|
+
logInfo(TAG, `Generated skills_catalog.md (${entries.length} skills${skippedStr})`);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
logWarn(TAG, `Failed to write skills_catalog.md: ${err instanceof Error ? err.message : String(err)}`);
|
|
89
|
+
}
|
|
90
|
+
return entries.length;
|
|
91
|
+
}
|
|
92
|
+
/** Check all requirements. Returns eligible=true only if ALL pass. */
|
|
93
|
+
checkEligibility(requires) {
|
|
94
|
+
const missing = [];
|
|
95
|
+
for (const bin of requires.bins ?? []) {
|
|
96
|
+
if (!this.binaryAvailable(bin)) missing.push(`bin:${bin}`);
|
|
97
|
+
}
|
|
98
|
+
for (const pkg of requires.npm ?? []) {
|
|
99
|
+
if (!this.npmAvailable(pkg)) missing.push(`npm:${pkg}`);
|
|
100
|
+
}
|
|
101
|
+
for (const key of requires.env ?? []) {
|
|
102
|
+
if (!process.env[key]) missing.push(`env:${key}`);
|
|
103
|
+
}
|
|
104
|
+
for (const file of requires.files ?? []) {
|
|
105
|
+
const resolved = resolve(file.replace(/^~/, homedir()));
|
|
106
|
+
if (!existsSync(resolved)) missing.push(`file:${file}`);
|
|
107
|
+
}
|
|
108
|
+
return { eligible: missing.length === 0, missing };
|
|
109
|
+
}
|
|
110
|
+
/** Check if an npm package is resolvable from the abtars node_modules. */
|
|
111
|
+
npmAvailable(pkg) {
|
|
112
|
+
try {
|
|
113
|
+
__require.resolve(pkg);
|
|
114
|
+
return true;
|
|
115
|
+
} catch (err) {
|
|
116
|
+
logAndSwallow(TAG, `require.resolve ${pkg}`, err);
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** Check if a binary is on PATH. Cached per-instance so hot-reload ticks don't respawn `which`. */
|
|
121
|
+
binaryAvailable(bin) {
|
|
122
|
+
if (!this.binaryCache.has(bin)) {
|
|
123
|
+
try {
|
|
124
|
+
execFileSync("which", [bin], { timeout: 1e3, stdio: "pipe" });
|
|
125
|
+
this.binaryCache.set(bin, true);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
logAndSwallow(TAG, `which ${bin}`, err);
|
|
128
|
+
this.binaryCache.set(bin, false);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return this.binaryCache.get(bin);
|
|
132
|
+
}
|
|
133
|
+
getSourceDir(filepath) {
|
|
134
|
+
const rel = filepath.slice(this.skillsDir.length + 1);
|
|
135
|
+
const first = rel.split("/")[0] ?? "core";
|
|
136
|
+
if (["core", "custom", "downloaded", "self"].includes(first)) return first;
|
|
137
|
+
return "core";
|
|
138
|
+
}
|
|
139
|
+
scanMdFiles(dir) {
|
|
140
|
+
const results = [];
|
|
141
|
+
try {
|
|
142
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
143
|
+
const full = join(dir, entry.name);
|
|
144
|
+
if (entry.isDirectory()) results.push(...this.scanMdFiles(full));
|
|
145
|
+
else if (entry.name === "SKILL.md") results.push(full);
|
|
146
|
+
}
|
|
147
|
+
} catch (err) {
|
|
148
|
+
logAndSwallow("skill_watcher", "op", err);
|
|
149
|
+
}
|
|
150
|
+
return results;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Parse a skill file's header.
|
|
154
|
+
*
|
|
155
|
+
* Preferred: YAML-style frontmatter block at the top of the file:
|
|
156
|
+
* ---
|
|
157
|
+
* name: mcporter
|
|
158
|
+
* description: Call external MCP servers via the mcporter CLI.
|
|
159
|
+
* requires: mcporter
|
|
160
|
+
* ---
|
|
161
|
+
*
|
|
162
|
+
* Supports only single-line `key: value` pairs. No arrays, no nested
|
|
163
|
+
* objects, no multi-line strings, no comments. Values are trimmed.
|
|
164
|
+
*
|
|
165
|
+
* Fallback (no frontmatter): first `#` heading → name, first non-heading
|
|
166
|
+
* line > 10 chars → description. Preserves pre-#369 behavior for any
|
|
167
|
+
* skills that don't yet have frontmatter.
|
|
168
|
+
*/
|
|
169
|
+
parseSkillHeader(filepath) {
|
|
170
|
+
try {
|
|
171
|
+
const content = readFileSync(filepath, "utf-8");
|
|
172
|
+
const fm = this.parseFrontmatter(content);
|
|
173
|
+
if (fm) {
|
|
174
|
+
return {
|
|
175
|
+
name: String(fm["name"] ?? "") || basename(dirname(filepath)),
|
|
176
|
+
description: String(fm["description"] ?? "").slice(0, 120),
|
|
177
|
+
...fm["requires"] ? { requires: this.parseRequires(fm["requires"]) } : {},
|
|
178
|
+
...fm["primaryEnv"] ? { primaryEnv: String(fm["primaryEnv"]) } : {}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const lines = content.split("\n").filter((l) => l.trim());
|
|
182
|
+
const heading = lines.find((l) => l.startsWith("#"));
|
|
183
|
+
const name = heading?.replace(/^#+\s*/, "").trim() ?? basename(dirname(filepath));
|
|
184
|
+
const desc = lines.find((l) => !l.startsWith("#") && l.trim().length > 10)?.trim() ?? "";
|
|
185
|
+
return { name, description: desc.slice(0, 120) };
|
|
186
|
+
} catch (err) {
|
|
187
|
+
logAndSwallow(TAG, "parseSkillMeta", err);
|
|
188
|
+
return { name: basename(dirname(filepath)), description: "" };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** Load ~/.abtars/config/skills.json (per-skill secrets). */
|
|
192
|
+
loadSkillsConfig() {
|
|
193
|
+
try {
|
|
194
|
+
const p = join(homedir(), ".abtars", "config", "skills.json");
|
|
195
|
+
if (!existsSync(p)) return {};
|
|
196
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
197
|
+
} catch (err) {
|
|
198
|
+
logAndSwallow("skill_watcher", "op", err);
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/** Parse requires field: string → { bins: [str] }, object → SkillRequires. */
|
|
203
|
+
parseRequires(raw) {
|
|
204
|
+
if (typeof raw === "string") return { bins: [raw] };
|
|
205
|
+
if (typeof raw === "object" && raw !== null) {
|
|
206
|
+
const obj = raw;
|
|
207
|
+
return {
|
|
208
|
+
...obj["bins"] ? { bins: toStringArray(obj["bins"]) } : {},
|
|
209
|
+
...obj["npm"] ? { npm: toStringArray(obj["npm"]) } : {},
|
|
210
|
+
...obj["env"] ? { env: toStringArray(obj["env"]) } : {},
|
|
211
|
+
...obj["files"] ? { files: toStringArray(obj["files"]) } : {}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return {};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Extract frontmatter key/value pairs. Returns null if the file doesn't
|
|
218
|
+
* start with a `---` fence.
|
|
219
|
+
*
|
|
220
|
+
* Supports: flat `key: value`, inline arrays `key: [a, b]`, and one level
|
|
221
|
+
* of nesting via indented keys under a parent.
|
|
222
|
+
*/
|
|
223
|
+
parseFrontmatter(content) {
|
|
224
|
+
const lines = content.split("\n");
|
|
225
|
+
let i = 0;
|
|
226
|
+
while (i < lines.length && lines[i].trim() === "") i++;
|
|
227
|
+
if (i >= lines.length || lines[i].trim() !== "---") return null;
|
|
228
|
+
const start = i + 1;
|
|
229
|
+
let end = -1;
|
|
230
|
+
for (let j = start; j < lines.length; j++) {
|
|
231
|
+
if (lines[j].trim() === "---") {
|
|
232
|
+
end = j;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (end === -1) return null;
|
|
237
|
+
const result = {};
|
|
238
|
+
let currentParent = null;
|
|
239
|
+
let currentObj = {};
|
|
240
|
+
for (let j = start; j < end; j++) {
|
|
241
|
+
const line = lines[j];
|
|
242
|
+
if (line.trim() === "") continue;
|
|
243
|
+
const indent = line.length - line.trimStart().length;
|
|
244
|
+
const colonIdx = line.indexOf(":");
|
|
245
|
+
if (colonIdx < 1) continue;
|
|
246
|
+
const key = line.slice(0, colonIdx).trim().toLowerCase();
|
|
247
|
+
const rawValue = line.slice(colonIdx + 1).trim();
|
|
248
|
+
if (indent > 0 && currentParent) {
|
|
249
|
+
currentObj[key] = parseYamlValue(rawValue);
|
|
250
|
+
} else {
|
|
251
|
+
if (currentParent) {
|
|
252
|
+
result[currentParent] = currentObj;
|
|
253
|
+
currentParent = null;
|
|
254
|
+
currentObj = {};
|
|
255
|
+
}
|
|
256
|
+
if (rawValue === "" || rawValue === "|" || rawValue === ">") {
|
|
257
|
+
currentParent = key;
|
|
258
|
+
currentObj = {};
|
|
259
|
+
} else {
|
|
260
|
+
result[key] = parseYamlValue(rawValue);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (currentParent) result[currentParent] = currentObj;
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
function parseYamlValue(raw) {
|
|
269
|
+
if (raw.startsWith("[") && raw.endsWith("]")) {
|
|
270
|
+
return raw.slice(1, -1).split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
|
|
271
|
+
}
|
|
272
|
+
return raw;
|
|
273
|
+
}
|
|
274
|
+
function toStringArray(val) {
|
|
275
|
+
if (Array.isArray(val)) return val.map(String);
|
|
276
|
+
if (typeof val === "string") return [val];
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/capabilities/hotskills/index.ts
|
|
281
|
+
init_paths();
|
|
282
|
+
function register(api) {
|
|
283
|
+
const skillWatcher = new SkillWatcher(
|
|
284
|
+
join2(abtarsHome(), "skills"),
|
|
285
|
+
join2(abtarsHome(), "core", "skills_catalog.md")
|
|
286
|
+
);
|
|
287
|
+
skillWatcher.generateCatalog();
|
|
288
|
+
api.registerCommand("skill", async (_text, ctx) => {
|
|
289
|
+
const count = skillWatcher.generateCatalog();
|
|
290
|
+
await ctx.reply(`Reloaded \u2014 ${count} skills available.`);
|
|
291
|
+
return true;
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export {
|
|
296
|
+
register,
|
|
297
|
+
hotskills_exports
|
|
298
|
+
};
|
|
299
|
+
//# sourceMappingURL=chunk-GUQVJC3U.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/capabilities/hotskills/index.ts", "../src/components/skill-watcher.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Skills capability \u2014 on-demand skill catalog reload via /skill command.\n */\n\nimport { join } from \"node:path\";\nimport { SkillWatcher } from \"../../components/skill-watcher.js\";\nimport { abtarsHome } from \"../../paths.js\";\nimport type { CapabilityApi } from \"../capability.js\";\n\nexport function register(api: CapabilityApi): void {\n const skillWatcher = new SkillWatcher(\n join(abtarsHome(), \"skills\"),\n join(abtarsHome(), \"core\", \"skills_catalog.md\"),\n );\n\n // Generate catalog on startup\n skillWatcher.generateCatalog();\n\n api.registerCommand(\"skill\", async (_text, ctx) => {\n const count = skillWatcher.generateCatalog();\n await ctx.reply(`Reloaded \u2014 ${count} skills available.`);\n return true;\n });\n}\n", "/**\n * SkillWatcher \u2014 generates skills_catalog.md on startup and on-demand via /skill reload.\n *\n * #369 \u2014 Parses YAML-style frontmatter to extract name/description/requires.\n * #412 \u2014 Structured requires: bins/npm/env/files.\n * Skills declare their own deps; loader checks eligibility at boot.\n */\n\nimport { logAndSwallow } from \"./log-and-swallow.js\";\nimport { readdirSync, readFileSync, writeFileSync, existsSync } from \"node:fs\";\nimport { join, basename, dirname, resolve } from \"node:path\";\nimport { execFileSync } from \"node:child_process\";\nimport { homedir } from \"node:os\";\nimport { logInfo, logWarn } from \"./logger.js\";\n\nimport type { ISkillSlot } from \"./skeleton.js\";\n\nconst TAG = \"skill-reloader\";\n\n/** Structured skill requirements (#412). */\ninterface SkillRequires {\n bins?: string[];\n npm?: string[];\n env?: string[];\n files?: string[];\n}\n\ninterface SkillHeader {\n name: string;\n description: string;\n requires?: SkillRequires;\n primaryEnv?: string;\n}\n\n/** Per-skill config from ~/.abtars/config/skills.json */\ninterface SkillsConfig {\n entries?: Record<string, { apiKey?: string; env?: Record<string, string> }>;\n}\n\nexport class SkillWatcher implements ISkillSlot {\n /** Per-instance cache of `which <bin>` results. Avoids repeated execFileSync on heartbeat ticks (#369). */\n private binaryCache = new Map<string, boolean>();\n\n constructor(private skillsDir: string, private catalogPath: string) {}\n\n /** Generate skills_catalog.md from all skill files. Called on startup + when skills change. */\n generateCatalog(): number {\n const files = this.scanMdFiles(this.skillsDir);\n const entries: string[] = [];\n const skipped: string[] = [];\n const skillsCfg = this.loadSkillsConfig();\n for (const filepath of files) {\n const header = this.parseSkillHeader(filepath);\n if (!header.name) continue;\n // Inject per-skill env from skills.json before eligibility check\n if (header.primaryEnv && !process.env[header.primaryEnv]) {\n const entry = skillsCfg.entries?.[header.name];\n if (entry?.apiKey) process.env[header.primaryEnv] = entry.apiKey;\n }\n const entry = skillsCfg.entries?.[header.name];\n if (entry?.env) {\n for (const [k, v] of Object.entries(entry.env)) {\n if (!process.env[k]) process.env[k] = v;\n }\n }\n if (header.requires) {\n const { eligible, missing } = this.checkEligibility(header.requires);\n if (!eligible) {\n skipped.push(`${header.name} (missing: ${missing.join(\", \")})`);\n continue;\n }\n }\n entries.push(`- [${this.getSourceDir(filepath)}] ${header.name}: ${header.description}`);\n }\n const guidance = [\n \"\",\n \"## Skill maintenance\",\n \"- If you solved something non-trivial (multi-step, error-prone, or likely to recur), save it as a skill with skill_create.\",\n \"- If a skill you just used was wrong or incomplete, fix it with skill_patch before moving on.\",\n \"\",\n ].join(\"\\n\");\n const content = `# Skills Catalog\\n\\nWhen a user request matches a skill below, read its SKILL.md at ~/.abtars/skills/<dir>/SKILL.md for detailed instructions before acting.\\n\\n${entries.join(\"\\n\")}\\n${guidance}`;\n try {\n writeFileSync(this.catalogPath, content, \"utf-8\");\n const skippedStr = skipped.length > 0 ? `, ${skipped.length} skipped \u2014 ${skipped.join(\", \")}` : \"\";\n logInfo(TAG, `Generated skills_catalog.md (${entries.length} skills${skippedStr})`);\n } catch (err) {\n logWarn(TAG, `Failed to write skills_catalog.md: ${err instanceof Error ? err.message : String(err)}`);\n }\n return entries.length;\n }\n\n /** Check all requirements. Returns eligible=true only if ALL pass. */\n private checkEligibility(requires: SkillRequires): { eligible: boolean; missing: string[] } {\n const missing: string[] = [];\n for (const bin of requires.bins ?? []) {\n if (!this.binaryAvailable(bin)) missing.push(`bin:${bin}`);\n }\n for (const pkg of requires.npm ?? []) {\n if (!this.npmAvailable(pkg)) missing.push(`npm:${pkg}`);\n }\n for (const key of requires.env ?? []) {\n if (!process.env[key]) missing.push(`env:${key}`);\n }\n for (const file of requires.files ?? []) {\n const resolved = resolve(file.replace(/^~/, homedir()));\n if (!existsSync(resolved)) missing.push(`file:${file}`);\n }\n return { eligible: missing.length === 0, missing };\n }\n\n /** Check if an npm package is resolvable from the abtars node_modules. */\n private npmAvailable(pkg: string): boolean {\n try {\n require.resolve(pkg);\n return true;\n } catch (err) {\n logAndSwallow(TAG, `require.resolve ${pkg}`, err);\n return false;\n }\n }\n\n /** Check if a binary is on PATH. Cached per-instance so hot-reload ticks don't respawn `which`. */\n private binaryAvailable(bin: string): boolean {\n if (!this.binaryCache.has(bin)) {\n try {\n // execFileSync (not execSync) \u2014 no shell interpolation on untrusted `requires:` values.\n execFileSync(\"which\", [bin], { timeout: 1000, stdio: \"pipe\" });\n this.binaryCache.set(bin, true);\n } catch (err) {\n logAndSwallow(TAG, `which ${bin}`, err);\n this.binaryCache.set(bin, false);\n }\n }\n return this.binaryCache.get(bin)!;\n }\n\n private getSourceDir(filepath: string): string {\n const rel = filepath.slice(this.skillsDir.length + 1);\n const first = rel.split(\"/\")[0] ?? \"core\";\n if ([\"core\", \"custom\", \"downloaded\", \"self\"].includes(first)) return first;\n return \"core\";\n }\n\n private scanMdFiles(dir: string): string[] {\n const results: string[] = [];\n try {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) results.push(...this.scanMdFiles(full));\n else if (entry.name === \"SKILL.md\") results.push(full);\n }\n } catch (err) { logAndSwallow(\"skill_watcher\", \"op\", err); }\n return results;\n }\n\n /**\n * Parse a skill file's header.\n *\n * Preferred: YAML-style frontmatter block at the top of the file:\n * ---\n * name: mcporter\n * description: Call external MCP servers via the mcporter CLI.\n * requires: mcporter\n * ---\n *\n * Supports only single-line `key: value` pairs. No arrays, no nested\n * objects, no multi-line strings, no comments. Values are trimmed.\n *\n * Fallback (no frontmatter): first `#` heading \u2192 name, first non-heading\n * line > 10 chars \u2192 description. Preserves pre-#369 behavior for any\n * skills that don't yet have frontmatter.\n */\n private parseSkillHeader(filepath: string): SkillHeader {\n try {\n const content = readFileSync(filepath, \"utf-8\");\n const fm = this.parseFrontmatter(content);\n if (fm) {\n return {\n name: String(fm[\"name\"] ?? \"\") || basename(dirname(filepath)),\n description: String(fm[\"description\"] ?? \"\").slice(0, 120),\n ...(fm[\"requires\"] ? { requires: this.parseRequires(fm[\"requires\"]) } : {}),\n ...(fm[\"primaryEnv\"] ? { primaryEnv: String(fm[\"primaryEnv\"]) } : {}),\n };\n }\n\n // Fallback for skill files without frontmatter\n const lines = content.split(\"\\n\").filter(l => l.trim());\n const heading = lines.find(l => l.startsWith(\"#\"));\n const name = heading?.replace(/^#+\\s*/, \"\").trim() ?? basename(dirname(filepath));\n const desc = lines.find(l => !l.startsWith(\"#\") && l.trim().length > 10)?.trim() ?? \"\";\n return { name, description: desc.slice(0, 120) };\n } catch (err) {\n logAndSwallow(TAG, \"parseSkillMeta\", err);\n return { name: basename(dirname(filepath)), description: \"\" };\n }\n }\n\n /** Load ~/.abtars/config/skills.json (per-skill secrets). */\n private loadSkillsConfig(): SkillsConfig {\n try {\n const p = join(homedir(), \".abtars\", \"config\", \"skills.json\");\n if (!existsSync(p)) return {};\n return JSON.parse(readFileSync(p, \"utf-8\")) as SkillsConfig;\n } catch (err) {\n logAndSwallow(\"skill_watcher\", \"op\", err);\n return {};\n }\n }\n\n /** Parse requires field: string \u2192 { bins: [str] }, object \u2192 SkillRequires. */\n private parseRequires(raw: unknown): SkillRequires {\n if (typeof raw === \"string\") return { bins: [raw] };\n if (typeof raw === \"object\" && raw !== null) {\n const obj = raw as Record<string, unknown>;\n return {\n ...(obj[\"bins\"] ? { bins: toStringArray(obj[\"bins\"]) } : {}),\n ...(obj[\"npm\"] ? { npm: toStringArray(obj[\"npm\"]) } : {}),\n ...(obj[\"env\"] ? { env: toStringArray(obj[\"env\"]) } : {}),\n ...(obj[\"files\"] ? { files: toStringArray(obj[\"files\"]) } : {}),\n };\n }\n return {};\n }\n\n /**\n * Extract frontmatter key/value pairs. Returns null if the file doesn't\n * start with a `---` fence.\n *\n * Supports: flat `key: value`, inline arrays `key: [a, b]`, and one level\n * of nesting via indented keys under a parent.\n */\n private parseFrontmatter(content: string): Record<string, unknown> | null {\n const lines = content.split(\"\\n\");\n let i = 0;\n while (i < lines.length && lines[i]!.trim() === \"\") i++;\n if (i >= lines.length || lines[i]!.trim() !== \"---\") return null;\n\n const start = i + 1;\n let end = -1;\n for (let j = start; j < lines.length; j++) {\n if (lines[j]!.trim() === \"---\") { end = j; break; }\n }\n if (end === -1) return null;\n\n const result: Record<string, unknown> = {};\n let currentParent: string | null = null;\n let currentObj: Record<string, unknown> = {};\n\n for (let j = start; j < end; j++) {\n const line = lines[j]!;\n if (line.trim() === \"\") continue;\n\n const indent = line.length - line.trimStart().length;\n const colonIdx = line.indexOf(\":\");\n if (colonIdx < 1) continue;\n\n const key = line.slice(0, colonIdx).trim().toLowerCase();\n const rawValue = line.slice(colonIdx + 1).trim();\n\n if (indent > 0 && currentParent) {\n // Nested key under parent\n currentObj[key] = parseYamlValue(rawValue);\n } else {\n // Top-level key\n if (currentParent) {\n result[currentParent] = currentObj;\n currentParent = null;\n currentObj = {};\n }\n if (rawValue === \"\" || rawValue === \"|\" || rawValue === \">\") {\n // Start of nested object\n currentParent = key;\n currentObj = {};\n } else {\n result[key] = parseYamlValue(rawValue);\n }\n }\n }\n if (currentParent) result[currentParent] = currentObj;\n\n return result;\n }\n}\n\n/** Parse a YAML value: inline array [a, b] \u2192 string[], otherwise string. */\nfunction parseYamlValue(raw: string): unknown {\n if (raw.startsWith(\"[\") && raw.endsWith(\"]\")) {\n return raw.slice(1, -1).split(\",\").map(s => s.trim().replace(/^[\"']|[\"']$/g, \"\")).filter(Boolean);\n }\n return raw;\n}\n\n/** Coerce unknown to string[]. */\nfunction toStringArray(val: unknown): string[] {\n if (Array.isArray(val)) return val.map(String);\n if (typeof val === \"string\") return [val];\n return [];\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["join", "entry", "join"]
|
|
7
|
+
}
|