agemon 6.0.0 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +313 -64
- package/assets/skills/design/agemon-design/NOTICE.md +34 -0
- package/assets/skills/design/agemon-design/SKILL.md +95 -358
- package/assets/skills/design/agemon-design/references/actions.md +215 -0
- package/assets/skills/design/agemon-design/references/brief.md +13 -9
- package/assets/skills/design/agemon-design/references/core-rules.md +166 -0
- package/assets/skills/design/agemon-design/references/craft-intent.md +16 -14
- package/assets/skills/design/agemon-design/references/dashboard.md +1 -1
- package/assets/skills/design/agemon-design/references/dataviz.md +8 -8
- package/assets/skills/design/agemon-design/references/finish-bar.md +1 -1
- package/assets/skills/design/agemon-design/references/heuristics.md +56 -140
- package/assets/skills/design/agemon-design/references/inspiration.md +6 -6
- package/assets/skills/design/agemon-design/references/loops.md +9 -9
- package/assets/skills/design/agemon-design/references/motion.md +1 -1
- package/assets/skills/design/agemon-design/references/personas.md +4 -4
- package/assets/skills/design/{agemon-design-dashboard/SKILL.md → agemon-design/references/preset-dashboard.md} +8 -12
- package/assets/skills/design/{agemon-design-editorial/SKILL.md → agemon-design/references/preset-editorial.md} +5 -9
- package/assets/skills/design/{agemon-design-minimal/SKILL.md → agemon-design/references/preset-minimal.md} +8 -12
- package/assets/skills/design/agemon-design/references/principles-catalog.md +3 -3
- package/assets/skills/design/agemon-design/references/recipe-auth.md +3 -3
- package/assets/skills/design/agemon-design/references/recipe-dashboard.md +2 -2
- package/assets/skills/design/agemon-design/references/recipe-landing.md +9 -11
- package/assets/skills/design/agemon-design/references/review.md +7 -7
- package/assets/skills/design/agemon-design/references/routing.md +143 -0
- package/assets/skills/design/agemon-design/references/spec.md +8 -8
- package/assets/skills/design/agemon-design/references/stack.md +1 -1
- package/assets/skills/design/agemon-design/references/stage-assets.md +106 -0
- package/assets/skills/design/agemon-design/references/stage-build.md +46 -0
- package/assets/skills/design/agemon-design/references/stage-critique.md +34 -0
- package/assets/skills/design/agemon-design/references/stage-directions.md +44 -0
- package/assets/skills/design/agemon-design/references/stage-intake.md +34 -0
- package/assets/skills/design/agemon-design/references/stage-verify.md +44 -0
- package/assets/skills/design/agemon-design/references/state-design.md +1 -1
- package/assets/skills/design/agemon-design/references/tells-2026-11.md +32 -0
- package/assets/skills/design/agemon-design/references/themes.md +24 -20
- package/assets/skills/design/agemon-design/references/third-party-licenses.md +323 -0
- package/assets/skills/design/agemon-design/references/typography.md +11 -9
- package/assets/skills/design/agemon-design/scripts/audit-page.js +532 -0
- package/assets/skills/design/agemon-design/scripts/check-source.mjs +358 -0
- package/assets/skills/design/agemon-design/scripts/deal.mjs +231 -0
- package/assets/skills/design/agemon-design/scripts/inventory.mjs +676 -0
- package/assets/skills/{design/agemon-design-dashboard → essentials/web-design-guidelines}/LICENSE +1 -1
- package/assets/skills/essentials/web-design-guidelines/NOTICE.md +14 -0
- package/assets/skills/essentials/web-design-guidelines/SKILL.md +18 -0
- package/assets/skills/essentials/web-design-guidelines/references/guidelines.md +184 -0
- package/assets/skills/{design/agemon-design-minimal → essentials/writing-guidelines}/LICENSE +1 -1
- package/assets/skills/essentials/writing-guidelines/NOTICE.md +14 -0
- package/assets/skills/essentials/writing-guidelines/SKILL.md +18 -0
- package/assets/skills/essentials/writing-guidelines/references/guidelines.md +250 -0
- package/assets/skills/founder/agemon-founder-board/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-board/NOTICE.md +11 -0
- package/assets/skills/founder/agemon-founder-board/SKILL.md +111 -0
- package/assets/skills/founder/agemon-founder-board/lenses.md +84 -0
- package/assets/skills/founder/agemon-founder-brand/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-brand/NOTICE.md +12 -0
- package/assets/skills/founder/agemon-founder-brand/SKILL.md +77 -0
- package/assets/skills/founder/agemon-founder-cfo/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-cfo/NOTICE.md +12 -0
- package/assets/skills/founder/agemon-founder-cfo/SKILL.md +109 -0
- package/assets/skills/founder/agemon-founder-cfo/example.json +27 -0
- package/assets/skills/founder/agemon-founder-cfo/unit_economics.py +270 -0
- package/assets/skills/founder/agemon-founder-competitors/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-competitors/NOTICE.md +12 -0
- package/assets/skills/founder/agemon-founder-competitors/SKILL.md +84 -0
- package/assets/skills/founder/agemon-founder-consumer/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-consumer/NOTICE.md +11 -0
- package/assets/skills/founder/agemon-founder-consumer/SKILL.md +126 -0
- package/assets/skills/founder/agemon-founder-consumer/customer.example.json +34 -0
- package/assets/skills/founder/agemon-founder-consumer/panel.py +424 -0
- package/assets/skills/founder/agemon-founder-consumer/pitch.example.md +3 -0
- package/assets/skills/founder/agemon-founder-launch/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-launch/NOTICE.md +11 -0
- package/assets/skills/founder/agemon-founder-launch/SKILL.md +65 -0
- package/assets/skills/founder/agemon-founder-marketing/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-marketing/NOTICE.md +11 -0
- package/assets/skills/founder/agemon-founder-marketing/SKILL.md +80 -0
- package/assets/skills/founder/agemon-founder-offer/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-offer/NOTICE.md +11 -0
- package/assets/skills/founder/agemon-founder-offer/SKILL.md +75 -0
- package/assets/skills/founder/agemon-founder-ops/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-ops/NOTICE.md +12 -0
- package/assets/skills/founder/agemon-founder-ops/SKILL.md +77 -0
- package/assets/skills/founder/agemon-founder-plan/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-plan/NOTICE.md +11 -0
- package/assets/skills/founder/agemon-founder-plan/SKILL.md +88 -0
- package/assets/skills/founder/agemon-founder-plan/compile.py +178 -0
- package/assets/skills/founder/agemon-founder-pricing/LICENSE +21 -0
- package/assets/skills/founder/agemon-founder-pricing/NOTICE.md +12 -0
- package/assets/skills/founder/agemon-founder-pricing/SKILL.md +92 -0
- package/assets/skills/founder/agemon-founder-pricing/van_westendorp.py +172 -0
- package/assets/skills/{design/agemon-design-editorial → output-style/agemon-adhd}/LICENSE +1 -1
- package/assets/skills/output-style/agemon-adhd/NOTICE.md +13 -0
- package/assets/skills/output-style/agemon-adhd/SKILL.md +138 -0
- package/assets/skills/security/agemon-security-audit/AI-AND-LLM.md +83 -0
- package/assets/skills/security/agemon-security-audit/ATTACK-CLASSES.md +130 -0
- package/assets/skills/security/agemon-security-audit/CLIENT-SIDE.md +83 -0
- package/assets/skills/security/agemon-security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
- package/assets/skills/security/agemon-security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
- package/assets/skills/security/agemon-security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
- package/assets/skills/security/agemon-security-audit/HUNTING.md +251 -0
- package/assets/skills/security/agemon-security-audit/LICENSE +21 -0
- package/assets/skills/security/agemon-security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
- package/assets/skills/security/agemon-security-audit/NOTICE.md +12 -0
- package/assets/skills/security/agemon-security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
- package/assets/skills/security/agemon-security-audit/RECONNAISSANCE.md +156 -0
- package/assets/skills/security/agemon-security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
- package/assets/skills/security/agemon-security-audit/SKILL.md +192 -0
- package/assets/skills/security/agemon-security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
- package/assets/skills/security/agemon-security-audit/VALIDATION-AND-REPORTING.md +186 -0
- package/assets/skills/security/agemon-security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
- package/assets/skills/security/agemon-security-audit/report-schema.json +461 -0
- package/assets/skills/security/agemon-security-audit/validate-coverage-ledger.cjs +872 -0
- package/assets/skills/security/agemon-security-audit/validate-findings.cjs +773 -0
- package/assets/skills/workflow/agemon-brainstorming/LICENSE +21 -0
- package/assets/skills/workflow/agemon-brainstorming/NOTICE.md +14 -0
- package/assets/skills/workflow/agemon-brainstorming/SKILL.md +287 -0
- package/assets/skills/workflow/agemon-brainstorming/builder-check-prompt.md +23 -0
- package/assets/skills/workflow/agemon-dispatching-parallel-agents/LICENSE +21 -0
- package/assets/skills/workflow/agemon-dispatching-parallel-agents/NOTICE.md +13 -0
- package/assets/skills/workflow/agemon-dispatching-parallel-agents/SKILL.md +167 -0
- package/assets/skills/workflow/agemon-executing-plans/LICENSE +21 -0
- package/assets/skills/workflow/agemon-executing-plans/NOTICE.md +15 -0
- package/assets/skills/workflow/agemon-executing-plans/SKILL.md +322 -0
- package/assets/skills/workflow/agemon-executing-plans/scripts/task-done +55 -0
- package/assets/skills/workflow/agemon-executing-plans/scripts/task-start +32 -0
- package/assets/skills/workflow/agemon-finishing-a-development-branch/LICENSE +21 -0
- package/assets/skills/workflow/agemon-finishing-a-development-branch/NOTICE.md +13 -0
- package/assets/skills/workflow/agemon-finishing-a-development-branch/SKILL.md +225 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/LICENSE +21 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/NOTICE.md +15 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/SKILL.md +339 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/code-reviewer.md +198 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/implementer-prompt.md +154 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/re-review-prompt.md +116 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/references/batching.md +11 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/references/cannot-verify.md +10 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/references/final-review.md +49 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/references/fix-loop.md +77 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/references/handling-reports.md +15 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/references/preflight.md +26 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/references/resuming.md +12 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/references/role-scout.md +18 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/references/role-worker.md +19 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/scripts/review-package +64 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/scripts/sdd-repo +54 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/scripts/sdd-workspace +110 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/scripts/task-brief +108 -0
- package/assets/skills/workflow/agemon-subagent-driven-development/task-reviewer-prompt.md +209 -0
- package/assets/skills/workflow/agemon-test-driven-development/LICENSE +21 -0
- package/assets/skills/workflow/agemon-test-driven-development/NOTICE.md +14 -0
- package/assets/skills/workflow/agemon-test-driven-development/SKILL.md +330 -0
- package/assets/skills/workflow/agemon-test-driven-development/writing-good-tests.md +198 -0
- package/assets/skills/workflow/agemon-using-git-worktrees/LICENSE +21 -0
- package/assets/skills/workflow/agemon-using-git-worktrees/NOTICE.md +13 -0
- package/assets/skills/workflow/agemon-using-git-worktrees/SKILL.md +167 -0
- package/assets/skills/workflow/agemon-writing-plans/LICENSE +21 -0
- package/assets/skills/workflow/agemon-writing-plans/NOTICE.md +13 -0
- package/assets/skills/workflow/agemon-writing-plans/SKILL.md +204 -0
- package/dist/{chunk-5LATHJYU.js → chunk-ZZBF3GOV.js} +369 -944
- package/dist/chunk-ZZBF3GOV.js.map +1 -0
- package/dist/{fake-subprocess-2BETWZVZ.js → fake-subprocess-IV4ML77S.js} +3 -33
- package/dist/fake-subprocess-IV4ML77S.js.map +1 -0
- package/dist/index.js +3477 -731
- package/dist/index.js.map +1 -1
- package/package.json +8 -1
- package/assets/skills/design/agemon-design/references/agents.md +0 -63
- package/assets/skills/design/agemon-design-dashboard/NOTICE.md +0 -9
- package/assets/skills/design/agemon-design-editorial/NOTICE.md +0 -9
- package/assets/skills/design/agemon-design-minimal/NOTICE.md +0 -9
- package/dist/chunk-5LATHJYU.js.map +0 -1
- package/dist/fake-subprocess-2BETWZVZ.js.map +0 -1
|
@@ -512,8 +512,6 @@ async function containsHomeDirectory(realDirectory) {
|
|
|
512
512
|
// src/plugins/pins.ts
|
|
513
513
|
var CODE_REVIEW_GRAPH_VERSION = "2.3.9";
|
|
514
514
|
var CODE_REVIEW_GRAPH_PACKAGE_SPEC = `code-review-graph==${CODE_REVIEW_GRAPH_VERSION}`;
|
|
515
|
-
var ESSENTIALS_SKILLS_REPOSITORY_URL = "https://github.com/vercel-labs/agent-skills.git";
|
|
516
|
-
var ESSENTIALS_SKILLS_COMMIT = "063bee94c3f4df8453406c830b0a7df0f2860278";
|
|
517
515
|
var AGNIX_VERSION = "0.58.0";
|
|
518
516
|
var AGNIX_RELEASE_ARCHIVE_SHA256 = {
|
|
519
517
|
"agnix-x86_64-unknown-linux-gnu.tar.gz": "68cbf435c87e89319133cd4fd4b8b0c8b0763b17862f231bf495ccb9d8ee074b",
|
|
@@ -563,17 +561,137 @@ function fingerprintContent(contents) {
|
|
|
563
561
|
return sha256Hex(contents);
|
|
564
562
|
}
|
|
565
563
|
|
|
566
|
-
// src/
|
|
564
|
+
// src/plugins/skills/skill-tree.ts
|
|
567
565
|
import { constants as constants3 } from "fs";
|
|
568
|
-
import {
|
|
566
|
+
import { lstat as lstat3, open as open3, opendir } from "fs/promises";
|
|
567
|
+
import { join as join2 } from "path";
|
|
568
|
+
var MAX_SKILL_ENTRIES = 200;
|
|
569
|
+
var MAX_SKILL_DEPTH = 8;
|
|
570
|
+
var MAX_SKILL_BYTES = 8 * 1024 * 1024;
|
|
571
|
+
var FINDER_METADATA_FILE = ".DS_Store";
|
|
572
|
+
var SKILLS_CLI_COPY_EXCLUSIONS = {
|
|
573
|
+
anyName: ["metadata.json"],
|
|
574
|
+
directoryNames: [".git", "__pycache__", "__pypackages__"]
|
|
575
|
+
};
|
|
576
|
+
var SkillTreeRefusal = class extends Error {
|
|
577
|
+
};
|
|
578
|
+
var keepEveryEntry = () => false;
|
|
579
|
+
function isLeftOutBySkillsCli(name, stats) {
|
|
580
|
+
return SKILLS_CLI_COPY_EXCLUSIONS.anyName.includes(name) || stats.isDirectory() && SKILLS_CLI_COPY_EXCLUSIONS.directoryNames.includes(
|
|
581
|
+
name
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
function isFinderMetadataFile(name, stats) {
|
|
585
|
+
return name === FINDER_METADATA_FILE && stats.isFile();
|
|
586
|
+
}
|
|
587
|
+
async function readRegularFileWithoutFollowing(path, maxBytes) {
|
|
588
|
+
const handle = await open3(
|
|
589
|
+
path,
|
|
590
|
+
constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK
|
|
591
|
+
);
|
|
592
|
+
try {
|
|
593
|
+
const stats = await handle.stat();
|
|
594
|
+
if (!stats.isFile()) {
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
if (stats.size > maxBytes) {
|
|
598
|
+
throw new SkillTreeRefusal("it is larger than 8 MiB");
|
|
599
|
+
}
|
|
600
|
+
return await handle.readFile();
|
|
601
|
+
} finally {
|
|
602
|
+
await handle.close();
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
async function sortedNamesUpToCap(directory) {
|
|
606
|
+
const names = [];
|
|
607
|
+
for await (const entry of await opendir(directory)) {
|
|
608
|
+
names.push(entry.name);
|
|
609
|
+
if (names.length > MAX_SKILL_ENTRIES) {
|
|
610
|
+
throw new SkillTreeRefusal(
|
|
611
|
+
`it has more than ${MAX_SKILL_ENTRIES} entries`
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return names.sort();
|
|
616
|
+
}
|
|
617
|
+
async function readSkillTree(directory, skipEntry = keepEveryEntry) {
|
|
618
|
+
const entries = [];
|
|
619
|
+
let totalBytes = 0;
|
|
620
|
+
const walk = async (relativeDirectory, depth) => {
|
|
621
|
+
if (depth > MAX_SKILL_DEPTH) {
|
|
622
|
+
throw new SkillTreeRefusal(
|
|
623
|
+
`it is nested deeper than ${MAX_SKILL_DEPTH} levels`
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
for (const name of await sortedNamesUpToCap(
|
|
627
|
+
join2(directory, relativeDirectory)
|
|
628
|
+
)) {
|
|
629
|
+
const relativePath = relativeDirectory === "" ? name : `${relativeDirectory}/${name}`;
|
|
630
|
+
const absolutePath = join2(directory, relativePath);
|
|
631
|
+
const stats = await lstat3(absolutePath);
|
|
632
|
+
if (skipEntry(name, stats)) {
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
if (entries.length >= MAX_SKILL_ENTRIES) {
|
|
636
|
+
throw new SkillTreeRefusal(
|
|
637
|
+
`it has more than ${MAX_SKILL_ENTRIES} entries`
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
if (stats.isDirectory()) {
|
|
641
|
+
entries.push({ relativePath, contents: null, mode: stats.mode });
|
|
642
|
+
await walk(relativePath, depth + 1);
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
const contents = stats.isFile() ? await readRegularFileWithoutFollowing(
|
|
646
|
+
absolutePath,
|
|
647
|
+
MAX_SKILL_BYTES - totalBytes
|
|
648
|
+
) : null;
|
|
649
|
+
if (contents === null) {
|
|
650
|
+
throw new SkillTreeRefusal(
|
|
651
|
+
`${printable(relativePath)} is a symlink or not a regular file`
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
totalBytes += contents.length;
|
|
655
|
+
if (totalBytes > MAX_SKILL_BYTES) {
|
|
656
|
+
throw new SkillTreeRefusal("it is larger than 8 MiB");
|
|
657
|
+
}
|
|
658
|
+
entries.push({ relativePath, contents, mode: stats.mode });
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
await walk("", 1);
|
|
662
|
+
return entries;
|
|
663
|
+
}
|
|
664
|
+
function fingerprintSkillTree(entries) {
|
|
665
|
+
return fingerprintJson(
|
|
666
|
+
entries.map((entry) => [
|
|
667
|
+
entry.relativePath,
|
|
668
|
+
entry.contents === null ? null : sha256Hex(entry.contents)
|
|
669
|
+
])
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
async function fingerprintSkillSource(directory) {
|
|
673
|
+
return fingerprintSkillTree(
|
|
674
|
+
await readSkillTree(directory, isLeftOutBySkillsCli)
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
function readInstalledSkill(directory) {
|
|
678
|
+
return readSkillTree(directory, isFinderMetadataFile);
|
|
679
|
+
}
|
|
680
|
+
async function fingerprintInstalledSkill(directory) {
|
|
681
|
+
return fingerprintSkillTree(await readInstalledSkill(directory));
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// src/core/state-root.ts
|
|
685
|
+
import { constants as constants4 } from "fs";
|
|
686
|
+
import { mkdir as mkdir2, open as open5, readFile as readFile2, realpath as realpath3, stat } from "fs/promises";
|
|
569
687
|
import { homedir as homedir2, userInfo as userInfo2 } from "os";
|
|
570
|
-
import { dirname as dirname2, isAbsolute as isAbsolute3, join as
|
|
688
|
+
import { dirname as dirname2, isAbsolute as isAbsolute3, join as join3 } from "path";
|
|
571
689
|
|
|
572
690
|
// src/core/file-lock.ts
|
|
573
691
|
import { AsyncLocalStorage } from "async_hooks";
|
|
574
692
|
import { execFile } from "child_process";
|
|
575
693
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
576
|
-
import { lstat as
|
|
694
|
+
import { lstat as lstat4, open as open4, readFile, rm as rm2 } from "fs/promises";
|
|
577
695
|
import { setTimeout as sleep } from "timers/promises";
|
|
578
696
|
var LOCK_FILE_MODE = 384;
|
|
579
697
|
var DEFAULT_POLL_MS = 200;
|
|
@@ -613,18 +731,18 @@ function processExists(pid) {
|
|
|
613
731
|
var linuxProcessProbe = {
|
|
614
732
|
bootId: () => readTrimmedOrNull("/proc/sys/kernel/random/boot_id"),
|
|
615
733
|
async startTime(pid) {
|
|
616
|
-
const
|
|
617
|
-
return
|
|
734
|
+
const stat2 = await readTrimmedOrNull(`/proc/${pid}/stat`);
|
|
735
|
+
return stat2 === null ? null : parseProcessStartTime(stat2);
|
|
618
736
|
},
|
|
619
737
|
exists: processExists
|
|
620
738
|
};
|
|
621
739
|
function readBootSessionUuidWithSysctl() {
|
|
622
|
-
return new Promise((
|
|
740
|
+
return new Promise((resolve3, reject) => {
|
|
623
741
|
execFile(
|
|
624
742
|
SYSCTL_PATH,
|
|
625
743
|
["-n", "kern.bootsessionuuid"],
|
|
626
744
|
{ timeout: SYSCTL_TIMEOUT_MS, maxBuffer: SYSCTL_OUTPUT_LIMIT_BYTES },
|
|
627
|
-
(error, stdout) => error ? reject(error) :
|
|
745
|
+
(error, stdout) => error ? reject(error) : resolve3(stdout)
|
|
628
746
|
);
|
|
629
747
|
});
|
|
630
748
|
}
|
|
@@ -675,7 +793,7 @@ async function isOwnerAlive(owner, probe) {
|
|
|
675
793
|
}
|
|
676
794
|
async function isOlderThan(path, ageMs) {
|
|
677
795
|
try {
|
|
678
|
-
return Date.now() - (await
|
|
796
|
+
return Date.now() - (await lstat4(path)).mtimeMs > ageMs;
|
|
679
797
|
} catch {
|
|
680
798
|
return false;
|
|
681
799
|
}
|
|
@@ -690,7 +808,7 @@ async function isStaleLock(lockPath, contents, probe) {
|
|
|
690
808
|
async function createLockFile(lockPath, contents) {
|
|
691
809
|
let handle;
|
|
692
810
|
try {
|
|
693
|
-
handle = await
|
|
811
|
+
handle = await open4(lockPath, "wx", LOCK_FILE_MODE);
|
|
694
812
|
} catch (error) {
|
|
695
813
|
if (error.code === "EEXIST") {
|
|
696
814
|
return false;
|
|
@@ -819,7 +937,7 @@ function resolveStateRoot(hostPlatform = process.platform) {
|
|
|
819
937
|
"Cannot locate agemon's state directory: set HOME (or XDG_STATE_HOME) to an absolute path."
|
|
820
938
|
);
|
|
821
939
|
}
|
|
822
|
-
return hostPlatform === "darwin" ?
|
|
940
|
+
return hostPlatform === "darwin" ? join3(homeDirectory, "Library", "Application Support") : join3(homeDirectory, ".local", "state");
|
|
823
941
|
}
|
|
824
942
|
async function readColonSeparatedRows(path) {
|
|
825
943
|
return (await readFile2(path, "utf8")).split("\n").filter((line) => line.length > 0).map((line) => line.split(":"));
|
|
@@ -876,9 +994,9 @@ async function assertSafeStateRoot(stateRoot, accounts) {
|
|
|
876
994
|
}
|
|
877
995
|
}
|
|
878
996
|
async function openAgemonDirectory(directory, mode) {
|
|
879
|
-
const flags =
|
|
997
|
+
const flags = constants4.O_RDONLY | constants4.O_DIRECTORY | constants4.O_NOFOLLOW;
|
|
880
998
|
try {
|
|
881
|
-
return await
|
|
999
|
+
return await open5(directory, flags);
|
|
882
1000
|
} catch (error) {
|
|
883
1001
|
const code = error.code;
|
|
884
1002
|
if (code === "ELOOP" || code === "ENOTDIR") {
|
|
@@ -902,7 +1020,7 @@ async function openAgemonDirectory(directory, mode) {
|
|
|
902
1020
|
}
|
|
903
1021
|
async function resolveAgemonStateDirectory(mode, accounts = currentAccounts()) {
|
|
904
1022
|
const stateRoot = resolveStateRoot();
|
|
905
|
-
const directory =
|
|
1023
|
+
const directory = join3(stateRoot, "agemon");
|
|
906
1024
|
if (mode === "prepare") {
|
|
907
1025
|
await mkdir2(stateRoot, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
|
|
908
1026
|
}
|
|
@@ -940,7 +1058,7 @@ async function checkAgemonStateDirectoryBeforeRun(dryRun, report) {
|
|
|
940
1058
|
}
|
|
941
1059
|
}
|
|
942
1060
|
async function preparePrivateStateDirectory(name) {
|
|
943
|
-
const directory =
|
|
1061
|
+
const directory = join3(
|
|
944
1062
|
(await resolveAgemonStateDirectory("prepare")).path,
|
|
945
1063
|
name
|
|
946
1064
|
);
|
|
@@ -957,7 +1075,7 @@ async function repositoryStateKey(repoRoot) {
|
|
|
957
1075
|
);
|
|
958
1076
|
}
|
|
959
1077
|
async function withAgemonStateLock(lockRelativePath, work, waitMs) {
|
|
960
|
-
const lockPath =
|
|
1078
|
+
const lockPath = join3(
|
|
961
1079
|
(await resolveAgemonStateDirectory("prepare")).path,
|
|
962
1080
|
lockRelativePath
|
|
963
1081
|
);
|
|
@@ -969,16 +1087,78 @@ async function withAgemonStateLock(lockRelativePath, work, waitMs) {
|
|
|
969
1087
|
}
|
|
970
1088
|
async function withRepositoryRunLock(repoRoot, work) {
|
|
971
1089
|
return withAgemonStateLock(
|
|
972
|
-
|
|
1090
|
+
join3("runs", `${await repositoryStateKey(repoRoot)}.lock`),
|
|
973
1091
|
() => work(),
|
|
974
1092
|
RUN_LOCK_WAIT_MS
|
|
975
1093
|
);
|
|
976
1094
|
}
|
|
977
1095
|
|
|
978
|
-
// src/plugins/skills/
|
|
979
|
-
import { existsSync } from "fs";
|
|
980
|
-
import {
|
|
981
|
-
|
|
1096
|
+
// src/plugins/skills/skills-cli.ts
|
|
1097
|
+
import { existsSync as existsSync2 } from "fs";
|
|
1098
|
+
import {
|
|
1099
|
+
copyFile,
|
|
1100
|
+
mkdtemp,
|
|
1101
|
+
readdir,
|
|
1102
|
+
readFile as readFile3,
|
|
1103
|
+
rename as rename2,
|
|
1104
|
+
rm as rm3
|
|
1105
|
+
} from "fs/promises";
|
|
1106
|
+
import { join as join5 } from "path";
|
|
1107
|
+
|
|
1108
|
+
// src/core/package-assets.ts
|
|
1109
|
+
import { existsSync, lstatSync, readFileSync } from "fs";
|
|
1110
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
1111
|
+
import { fileURLToPath } from "url";
|
|
1112
|
+
var PACKAGE_NAME = "agemon";
|
|
1113
|
+
var PACKAGE_MANIFEST = "package.json";
|
|
1114
|
+
var MAX_PACKAGE_MANIFEST_BYTES = 1024 * 1024;
|
|
1115
|
+
var cachedPackageRoot;
|
|
1116
|
+
function readPackageName(manifestPath) {
|
|
1117
|
+
const stats = lstatSync(manifestPath);
|
|
1118
|
+
if (!stats.isFile() || stats.size > MAX_PACKAGE_MANIFEST_BYTES) {
|
|
1119
|
+
return null;
|
|
1120
|
+
}
|
|
1121
|
+
try {
|
|
1122
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
1123
|
+
return typeof manifest === "object" && manifest !== null && "name" in manifest && typeof manifest.name === "string" ? manifest.name : null;
|
|
1124
|
+
} catch {
|
|
1125
|
+
return null;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
function findNearestPackageDirectory(startDirectory) {
|
|
1129
|
+
let currentDir = startDirectory;
|
|
1130
|
+
for (; ; ) {
|
|
1131
|
+
if (existsSync(join4(currentDir, PACKAGE_MANIFEST))) {
|
|
1132
|
+
return currentDir;
|
|
1133
|
+
}
|
|
1134
|
+
const parentDir = dirname3(currentDir);
|
|
1135
|
+
if (parentDir === currentDir) {
|
|
1136
|
+
return null;
|
|
1137
|
+
}
|
|
1138
|
+
currentDir = parentDir;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
function resolvePackageRootFrom(startDirectory) {
|
|
1142
|
+
const packageDirectory = findNearestPackageDirectory(startDirectory);
|
|
1143
|
+
if (packageDirectory === null || readPackageName(join4(packageDirectory, PACKAGE_MANIFEST)) !== PACKAGE_NAME || !existsSync(join4(packageDirectory, "assets", "skills"))) {
|
|
1144
|
+
throw new Error(
|
|
1145
|
+
"Unable to locate agemon's vendored assets/skills directory."
|
|
1146
|
+
);
|
|
1147
|
+
}
|
|
1148
|
+
return packageDirectory;
|
|
1149
|
+
}
|
|
1150
|
+
function resolvePackageRoot() {
|
|
1151
|
+
cachedPackageRoot ??= resolvePackageRootFrom(
|
|
1152
|
+
dirname3(fileURLToPath(import.meta.url))
|
|
1153
|
+
);
|
|
1154
|
+
return cachedPackageRoot;
|
|
1155
|
+
}
|
|
1156
|
+
function resolveVendoredSkillPath(groupId, skillId) {
|
|
1157
|
+
return join4(resolvePackageRoot(), "assets", "skills", groupId, skillId);
|
|
1158
|
+
}
|
|
1159
|
+
function resolveToolsManifestDirectory() {
|
|
1160
|
+
return join4(resolvePackageRoot(), "assets", "tools");
|
|
1161
|
+
}
|
|
982
1162
|
|
|
983
1163
|
// src/core/subprocess-runner.ts
|
|
984
1164
|
import { spawn } from "child_process";
|
|
@@ -1030,6 +1210,9 @@ var MAX_REDACTED_LINE_CHARACTERS = 4096;
|
|
|
1030
1210
|
var HIGH_ENTROPY_MIN_LENGTH = 32;
|
|
1031
1211
|
var HIGH_ENTROPY_MIN_BITS_PER_CHAR = 3.5;
|
|
1032
1212
|
var HIGH_ENTROPY_CHARSET = /^[A-Za-z0-9+/=_-]+$/;
|
|
1213
|
+
var MIN_PATH_SEGMENTS = 3;
|
|
1214
|
+
var MIXED_SEGMENT_MIN_LENGTH = 16;
|
|
1215
|
+
var WORD_SEPARATOR = /[-_]/;
|
|
1033
1216
|
function isDenylistedPath(relativePath) {
|
|
1034
1217
|
return DENYLISTED_FILE_PATTERNS.some((pattern) => pattern.test(relativePath));
|
|
1035
1218
|
}
|
|
@@ -1045,8 +1228,21 @@ function shannonEntropyBitsPerChar(value) {
|
|
|
1045
1228
|
}
|
|
1046
1229
|
return bitsPerChar;
|
|
1047
1230
|
}
|
|
1231
|
+
function mixesCasesAndDigits(value) {
|
|
1232
|
+
return /[A-Z]/.test(value) && /[a-z]/.test(value) && /[0-9]/.test(value);
|
|
1233
|
+
}
|
|
1234
|
+
function looksLikeSecretPathSegment(segment) {
|
|
1235
|
+
if (shannonEntropyBitsPerChar(segment) < HIGH_ENTROPY_MIN_BITS_PER_CHAR) {
|
|
1236
|
+
return false;
|
|
1237
|
+
}
|
|
1238
|
+
return segment.length >= MIXED_SEGMENT_MIN_LENGTH && mixesCasesAndDigits(segment) || segment.length >= HIGH_ENTROPY_MIN_LENGTH && !WORD_SEPARATOR.test(segment);
|
|
1239
|
+
}
|
|
1240
|
+
function looksLikeWordPath(value) {
|
|
1241
|
+
const segments = value.split("/");
|
|
1242
|
+
return value.startsWith("/") && segments.length >= MIN_PATH_SEGMENTS && !segments.some(looksLikeSecretPathSegment);
|
|
1243
|
+
}
|
|
1048
1244
|
function looksHighEntropy(value) {
|
|
1049
|
-
return value.length >= HIGH_ENTROPY_MIN_LENGTH && HIGH_ENTROPY_CHARSET.test(value) && shannonEntropyBitsPerChar(value) >= HIGH_ENTROPY_MIN_BITS_PER_CHAR;
|
|
1245
|
+
return value.length >= HIGH_ENTROPY_MIN_LENGTH && HIGH_ENTROPY_CHARSET.test(value) && shannonEntropyBitsPerChar(value) >= HIGH_ENTROPY_MIN_BITS_PER_CHAR && !looksLikeWordPath(value);
|
|
1050
1246
|
}
|
|
1051
1247
|
function stripKeyDecoration(rawKey) {
|
|
1052
1248
|
return rawKey.replace(/^[-"']+/, "").replace(/["':]+$/, "");
|
|
@@ -1318,706 +1514,132 @@ function createBoundedCapture() {
|
|
|
1318
1514
|
text += `${sliceWithoutSplittingSurrogatePair(chunk, remainingCharacters)}${TRUNCATION_MARKER}`;
|
|
1319
1515
|
truncated = true;
|
|
1320
1516
|
},
|
|
1321
|
-
get text() {
|
|
1322
|
-
return text;
|
|
1323
|
-
}
|
|
1324
|
-
};
|
|
1325
|
-
}
|
|
1326
|
-
async function runSubprocess(command, args, options = {}) {
|
|
1327
|
-
if (process.env.AGEMON_FAKE_SUBPROCESS === "1") {
|
|
1328
|
-
const { runFakeSubprocess } = await import("./fake-subprocess-2BETWZVZ.js");
|
|
1329
|
-
return runFakeSubprocess(command, args, options);
|
|
1330
|
-
}
|
|
1331
|
-
return runRealSubprocess(command, args, options);
|
|
1332
|
-
}
|
|
1333
|
-
async function runRealSubprocess(command, args, options = {}) {
|
|
1334
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_SUBPROCESS_TIMEOUT_MS;
|
|
1335
|
-
return await new Promise((resolve4) => {
|
|
1336
|
-
let settled = false;
|
|
1337
|
-
let timedOut = false;
|
|
1338
|
-
let timeoutHandle;
|
|
1339
|
-
let hardKillHandle;
|
|
1340
|
-
let drainHandle;
|
|
1341
|
-
const stdout = createBoundedCapture();
|
|
1342
|
-
const stderr = createBoundedCapture();
|
|
1343
|
-
const clearTimers = () => {
|
|
1344
|
-
clearTimeout(timeoutHandle);
|
|
1345
|
-
clearTimeout(hardKillHandle);
|
|
1346
|
-
clearTimeout(drainHandle);
|
|
1347
|
-
};
|
|
1348
|
-
const finalize = (result) => {
|
|
1349
|
-
if (settled) {
|
|
1350
|
-
return;
|
|
1351
|
-
}
|
|
1352
|
-
settled = true;
|
|
1353
|
-
clearTimers();
|
|
1354
|
-
resolve4(result);
|
|
1355
|
-
};
|
|
1356
|
-
const resultForExit = (code, signal) => {
|
|
1357
|
-
if (timedOut) {
|
|
1358
|
-
const timeoutMessage = `Command timed out after ${timeoutMs}ms.`;
|
|
1359
|
-
return {
|
|
1360
|
-
code: TIMEOUT_EXIT_CODE,
|
|
1361
|
-
stdout: stdout.text,
|
|
1362
|
-
stderr: stderr.text ? `${stderr.text}
|
|
1363
|
-
${timeoutMessage}` : timeoutMessage
|
|
1364
|
-
};
|
|
1365
|
-
}
|
|
1366
|
-
if (signal) {
|
|
1367
|
-
return {
|
|
1368
|
-
code: 1,
|
|
1369
|
-
stdout: stdout.text,
|
|
1370
|
-
stderr: `${stderr.text}Process terminated by signal: ${signal}`
|
|
1371
|
-
};
|
|
1372
|
-
}
|
|
1373
|
-
return { code: code ?? 1, stdout: stdout.text, stderr: stderr.text };
|
|
1374
|
-
};
|
|
1375
|
-
const finalizeAfterDrainGrace = (code, signal) => {
|
|
1376
|
-
clearTimeout(drainHandle);
|
|
1377
|
-
drainHandle = setTimeout(() => {
|
|
1378
|
-
childProcess.stdout.destroy();
|
|
1379
|
-
childProcess.stderr.destroy();
|
|
1380
|
-
finalize(resultForExit(code, signal));
|
|
1381
|
-
}, STREAM_DRAIN_GRACE_MS);
|
|
1382
|
-
};
|
|
1383
|
-
const environment = {
|
|
1384
|
-
...agemonSubprocessEnvironment(),
|
|
1385
|
-
...options.env
|
|
1386
|
-
};
|
|
1387
|
-
for (const name of options.unsetEnv ?? []) {
|
|
1388
|
-
delete environment[name];
|
|
1389
|
-
}
|
|
1390
|
-
const childProcess = spawn(command, args, {
|
|
1391
|
-
cwd: options.cwd ?? process.cwd(),
|
|
1392
|
-
env: environment,
|
|
1393
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
1394
|
-
});
|
|
1395
|
-
if (timeoutMs > 0) {
|
|
1396
|
-
timeoutHandle = setTimeout(() => {
|
|
1397
|
-
timedOut = true;
|
|
1398
|
-
const signal = options.killSignal ?? "SIGTERM";
|
|
1399
|
-
const terminated = childProcess.kill(signal);
|
|
1400
|
-
if (!terminated) {
|
|
1401
|
-
finalize({
|
|
1402
|
-
code: TIMEOUT_EXIT_CODE,
|
|
1403
|
-
stdout: stdout.text,
|
|
1404
|
-
stderr: `${stderr.text}
|
|
1405
|
-
Command timed out after ${timeoutMs}ms and could not be signaled with ${signal}.`
|
|
1406
|
-
});
|
|
1407
|
-
return;
|
|
1408
|
-
}
|
|
1409
|
-
hardKillHandle = setTimeout(() => {
|
|
1410
|
-
childProcess.kill("SIGKILL");
|
|
1411
|
-
finalizeAfterDrainGrace(null, "SIGKILL");
|
|
1412
|
-
}, HARD_KILL_GRACE_MS);
|
|
1413
|
-
}, timeoutMs);
|
|
1414
|
-
}
|
|
1415
|
-
childProcess.stdout.setEncoding("utf8");
|
|
1416
|
-
childProcess.stderr.setEncoding("utf8");
|
|
1417
|
-
childProcess.stdout.on("data", (chunk) => stdout.append(chunk));
|
|
1418
|
-
childProcess.stderr.on("data", (chunk) => stderr.append(chunk));
|
|
1419
|
-
childProcess.on("error", (error) => {
|
|
1420
|
-
const errorMessage = stderr.text ? `${stderr.text}
|
|
1421
|
-
${SPAWN_ERROR_PREFIX}${error.message}` : `${SPAWN_ERROR_PREFIX}${error.message}`;
|
|
1422
|
-
finalize({ code: 1, stdout: stdout.text, stderr: errorMessage });
|
|
1423
|
-
});
|
|
1424
|
-
childProcess.on(
|
|
1425
|
-
"exit",
|
|
1426
|
-
(code, signal) => {
|
|
1427
|
-
clearTimeout(timeoutHandle);
|
|
1428
|
-
clearTimeout(hardKillHandle);
|
|
1429
|
-
finalizeAfterDrainGrace(code, signal);
|
|
1430
|
-
}
|
|
1431
|
-
);
|
|
1432
|
-
childProcess.on(
|
|
1433
|
-
"close",
|
|
1434
|
-
(code, signal) => {
|
|
1435
|
-
finalize(resultForExit(code, signal));
|
|
1436
|
-
}
|
|
1437
|
-
);
|
|
1438
|
-
});
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
// src/plugins/skills/pinned-source.ts
|
|
1442
|
-
var SOURCE_DIRECTORY_MODE = 448;
|
|
1443
|
-
var GIT_STEP_TIMEOUT_MS = 12e4;
|
|
1444
|
-
var GIT_SYMLINK_MODE = "120000";
|
|
1445
|
-
var GIT_WITHOUT_HOOKS_ARGS = [
|
|
1446
|
-
"-c",
|
|
1447
|
-
"core.hooksPath=/dev/null",
|
|
1448
|
-
"-c",
|
|
1449
|
-
"core.fsmonitor=false",
|
|
1450
|
-
"-c",
|
|
1451
|
-
"credential.helper="
|
|
1452
|
-
];
|
|
1453
|
-
function resolvePinnedSkillsSourceDirectory(commit) {
|
|
1454
|
-
return join3(resolveStateRoot(), "agemon", "skills-src", commit);
|
|
1455
|
-
}
|
|
1456
|
-
async function localGitOutput(ctx, sourceDirectory, subcommandArgs) {
|
|
1457
|
-
const result = await ctx.run(
|
|
1458
|
-
"git",
|
|
1459
|
-
[...GIT_WITHOUT_HOOKS_ARGS, ...subcommandArgs],
|
|
1460
|
-
{
|
|
1461
|
-
cwd: sourceDirectory,
|
|
1462
|
-
timeoutMs: GIT_STEP_TIMEOUT_MS,
|
|
1463
|
-
env: isolatedGitEnvironment(sourceDirectory)
|
|
1464
|
-
}
|
|
1465
|
-
);
|
|
1466
|
-
return result.code === 0 ? result.stdout : null;
|
|
1467
|
-
}
|
|
1468
|
-
async function isPristinePinnedCheckout(ctx, repository) {
|
|
1469
|
-
const sourceDirectory = resolvePinnedSkillsSourceDirectory(repository.commit);
|
|
1470
|
-
if (!existsSync(join3(sourceDirectory, ".git"))) {
|
|
1471
|
-
return false;
|
|
1472
|
-
}
|
|
1473
|
-
try {
|
|
1474
|
-
const head = await localGitOutput(ctx, sourceDirectory, [
|
|
1475
|
-
"rev-parse",
|
|
1476
|
-
"--verify",
|
|
1477
|
-
"--end-of-options",
|
|
1478
|
-
"HEAD^{commit}"
|
|
1479
|
-
]);
|
|
1480
|
-
if (head?.trim() !== repository.commit) {
|
|
1481
|
-
return false;
|
|
1482
|
-
}
|
|
1483
|
-
const status = await localGitOutput(ctx, sourceDirectory, [
|
|
1484
|
-
"status",
|
|
1485
|
-
"--porcelain",
|
|
1486
|
-
"--ignored"
|
|
1487
|
-
]);
|
|
1488
|
-
return status !== null && status.trim() === "";
|
|
1489
|
-
} catch {
|
|
1490
|
-
return false;
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
function skillPathInRepository(skillName) {
|
|
1494
|
-
return `skills/${skillName}`;
|
|
1495
|
-
}
|
|
1496
|
-
function resolvePinnedSkillPath(repository, skillName) {
|
|
1497
|
-
return join3(
|
|
1498
|
-
resolvePinnedSkillsSourceDirectory(repository.commit),
|
|
1499
|
-
skillPathInRepository(skillName)
|
|
1500
|
-
);
|
|
1501
|
-
}
|
|
1502
|
-
function isolatedGitEnvironment(sourceDirectory) {
|
|
1503
|
-
const gitDirectory = join3(sourceDirectory, ".git");
|
|
1504
|
-
return {
|
|
1505
|
-
GIT_TERMINAL_PROMPT: "0",
|
|
1506
|
-
GIT_CONFIG_GLOBAL: "/dev/null",
|
|
1507
|
-
GIT_CONFIG_NOSYSTEM: "1",
|
|
1508
|
-
GIT_CONFIG_COUNT: "0",
|
|
1509
|
-
GIT_CONFIG_PARAMETERS: "",
|
|
1510
|
-
GIT_ASKPASS: "",
|
|
1511
|
-
SSH_ASKPASS: "",
|
|
1512
|
-
GIT_DIR: gitDirectory,
|
|
1513
|
-
GIT_WORK_TREE: sourceDirectory,
|
|
1514
|
-
GIT_COMMON_DIR: gitDirectory,
|
|
1515
|
-
GIT_INDEX_FILE: join3(gitDirectory, "index"),
|
|
1516
|
-
GIT_OBJECT_DIRECTORY: join3(gitDirectory, "objects"),
|
|
1517
|
-
GIT_ALTERNATE_OBJECT_DIRECTORIES: ""
|
|
1518
|
-
};
|
|
1519
|
-
}
|
|
1520
|
-
async function runGitStep(ctx, sourceDirectory, subcommandArgs) {
|
|
1521
|
-
const result = await ctx.run(
|
|
1522
|
-
"git",
|
|
1523
|
-
[...GIT_WITHOUT_HOOKS_ARGS, ...subcommandArgs],
|
|
1524
|
-
{
|
|
1525
|
-
cwd: sourceDirectory,
|
|
1526
|
-
timeoutMs: GIT_STEP_TIMEOUT_MS,
|
|
1527
|
-
env: isolatedGitEnvironment(sourceDirectory)
|
|
1528
|
-
}
|
|
1529
|
-
);
|
|
1530
|
-
if (result.code !== 0) {
|
|
1531
|
-
throw new Error(
|
|
1532
|
-
`git ${subcommandArgs[0]} failed while fetching pinned skills: ${describeSubprocessFailure(result, "git")}`
|
|
1533
|
-
);
|
|
1534
|
-
}
|
|
1535
|
-
return result;
|
|
1536
|
-
}
|
|
1537
|
-
function findSymlinkPaths(lsTreeOutput) {
|
|
1538
|
-
return lsTreeOutput.split("\n").filter((line) => line.startsWith(`${GIT_SYMLINK_MODE} `)).map((line) => line.slice(line.indexOf(" ") + 1));
|
|
1539
|
-
}
|
|
1540
|
-
async function assertSkillIsPlainFiles(ctx, sourceDirectory, skillName) {
|
|
1541
|
-
const skillPath = skillPathInRepository(skillName);
|
|
1542
|
-
const listing = await runGitStep(ctx, sourceDirectory, [
|
|
1543
|
-
"ls-tree",
|
|
1544
|
-
"-r",
|
|
1545
|
-
"HEAD",
|
|
1546
|
-
"--",
|
|
1547
|
-
skillPath
|
|
1548
|
-
]);
|
|
1549
|
-
if (listing.stdout.trim().length === 0) {
|
|
1550
|
-
throw new Error(`The pinned skills commit has no ${skillPath}.`);
|
|
1551
|
-
}
|
|
1552
|
-
const symlinkPaths = findSymlinkPaths(listing.stdout);
|
|
1553
|
-
if (symlinkPaths.length > 0) {
|
|
1554
|
-
throw new Error(
|
|
1555
|
-
`Refusing to install pinned skills: ${symlinkPaths.map(printable).join(", ")} is a symlink.`
|
|
1556
|
-
);
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1559
|
-
async function fetchPinnedSkillsSource(ctx, repository, skillNames) {
|
|
1560
|
-
const sourceDirectory = resolvePinnedSkillsSourceDirectory(repository.commit);
|
|
1561
|
-
await rm3(sourceDirectory, { recursive: true, force: true });
|
|
1562
|
-
await mkdir3(sourceDirectory, {
|
|
1563
|
-
recursive: true,
|
|
1564
|
-
mode: SOURCE_DIRECTORY_MODE
|
|
1565
|
-
});
|
|
1566
|
-
await runGitStep(ctx, sourceDirectory, ["init", "-q"]);
|
|
1567
|
-
await runGitStep(ctx, sourceDirectory, [
|
|
1568
|
-
"fetch",
|
|
1569
|
-
"--depth",
|
|
1570
|
-
"1",
|
|
1571
|
-
repository.url,
|
|
1572
|
-
repository.commit
|
|
1573
|
-
]);
|
|
1574
|
-
await runGitStep(ctx, sourceDirectory, ["checkout", "-q", "FETCH_HEAD"]);
|
|
1575
|
-
const head = (await runGitStep(ctx, sourceDirectory, ["rev-parse", "HEAD"])).stdout.trim();
|
|
1576
|
-
if (head !== repository.commit) {
|
|
1577
|
-
throw new Error(
|
|
1578
|
-
`Pinned skills checkout mismatch: expected commit ${repository.commit}, got ${printable(head)}.`
|
|
1579
|
-
);
|
|
1580
|
-
}
|
|
1581
|
-
for (const skillName of skillNames) {
|
|
1582
|
-
await assertSkillIsPlainFiles(ctx, sourceDirectory, skillName);
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
|
-
// src/plugins/skills/catalog.ts
|
|
1587
|
-
import { join as join5 } from "path";
|
|
1588
|
-
|
|
1589
|
-
// src/core/package-assets.ts
|
|
1590
|
-
import { existsSync as existsSync2, lstatSync, readFileSync } from "fs";
|
|
1591
|
-
import { dirname as dirname3, join as join4 } from "path";
|
|
1592
|
-
import { fileURLToPath } from "url";
|
|
1593
|
-
var PACKAGE_NAME = "agemon";
|
|
1594
|
-
var PACKAGE_MANIFEST = "package.json";
|
|
1595
|
-
var MAX_PACKAGE_MANIFEST_BYTES = 1024 * 1024;
|
|
1596
|
-
var cachedPackageRoot;
|
|
1597
|
-
function readPackageName(manifestPath) {
|
|
1598
|
-
const stats = lstatSync(manifestPath);
|
|
1599
|
-
if (!stats.isFile() || stats.size > MAX_PACKAGE_MANIFEST_BYTES) {
|
|
1600
|
-
return null;
|
|
1601
|
-
}
|
|
1602
|
-
try {
|
|
1603
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
1604
|
-
return typeof manifest === "object" && manifest !== null && "name" in manifest && typeof manifest.name === "string" ? manifest.name : null;
|
|
1605
|
-
} catch {
|
|
1606
|
-
return null;
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
function findNearestPackageDirectory(startDirectory) {
|
|
1610
|
-
let currentDir = startDirectory;
|
|
1611
|
-
for (; ; ) {
|
|
1612
|
-
if (existsSync2(join4(currentDir, PACKAGE_MANIFEST))) {
|
|
1613
|
-
return currentDir;
|
|
1614
|
-
}
|
|
1615
|
-
const parentDir = dirname3(currentDir);
|
|
1616
|
-
if (parentDir === currentDir) {
|
|
1617
|
-
return null;
|
|
1618
|
-
}
|
|
1619
|
-
currentDir = parentDir;
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
function resolvePackageRootFrom(startDirectory) {
|
|
1623
|
-
const packageDirectory = findNearestPackageDirectory(startDirectory);
|
|
1624
|
-
if (packageDirectory === null || readPackageName(join4(packageDirectory, PACKAGE_MANIFEST)) !== PACKAGE_NAME || !existsSync2(join4(packageDirectory, "assets", "skills"))) {
|
|
1625
|
-
throw new Error(
|
|
1626
|
-
"Unable to locate agemon's vendored assets/skills directory."
|
|
1627
|
-
);
|
|
1628
|
-
}
|
|
1629
|
-
return packageDirectory;
|
|
1630
|
-
}
|
|
1631
|
-
function resolvePackageRoot() {
|
|
1632
|
-
cachedPackageRoot ??= resolvePackageRootFrom(
|
|
1633
|
-
dirname3(fileURLToPath(import.meta.url))
|
|
1634
|
-
);
|
|
1635
|
-
return cachedPackageRoot;
|
|
1636
|
-
}
|
|
1637
|
-
function resolveVendoredSkillPath(groupId, skillId) {
|
|
1638
|
-
return join4(resolvePackageRoot(), "assets", "skills", groupId, skillId);
|
|
1639
|
-
}
|
|
1640
|
-
function resolveToolsManifestDirectory() {
|
|
1641
|
-
return join4(resolvePackageRoot(), "assets", "tools");
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
// src/plugins/skills/catalog.ts
|
|
1645
|
-
var ESSENTIALS_REPOSITORY = {
|
|
1646
|
-
url: ESSENTIALS_SKILLS_REPOSITORY_URL,
|
|
1647
|
-
commit: ESSENTIALS_SKILLS_COMMIT
|
|
1648
|
-
};
|
|
1649
|
-
var GEO_AUDIT_AGENT_DESCRIPTION_SUFFIX = "Used by the geo-audit skill; do not use it for other tasks.";
|
|
1650
|
-
function vendoredSkill(groupId, skillId) {
|
|
1651
|
-
return {
|
|
1652
|
-
id: skillId,
|
|
1653
|
-
get source() {
|
|
1654
|
-
return resolveVendoredSkillPath(groupId, skillId);
|
|
1655
|
-
},
|
|
1656
|
-
skillName: skillId,
|
|
1657
|
-
agent: "claude-code"
|
|
1658
|
-
};
|
|
1659
|
-
}
|
|
1660
|
-
function pinnedSkill(repository, skillId) {
|
|
1661
|
-
return {
|
|
1662
|
-
id: skillId,
|
|
1663
|
-
get source() {
|
|
1664
|
-
return resolvePinnedSkillPath(repository, skillId);
|
|
1665
|
-
},
|
|
1666
|
-
skillName: skillId,
|
|
1667
|
-
agent: "claude-code",
|
|
1668
|
-
pinnedRepository: repository
|
|
1669
|
-
};
|
|
1670
|
-
}
|
|
1671
|
-
function geoAuditAgent(name, briefFileName, purpose, tools) {
|
|
1672
|
-
return {
|
|
1673
|
-
name,
|
|
1674
|
-
description: `${purpose} ${GEO_AUDIT_AGENT_DESCRIPTION_SUFFIX}`,
|
|
1675
|
-
tools,
|
|
1676
|
-
get briefPath() {
|
|
1677
|
-
return join5(
|
|
1678
|
-
resolveVendoredSkillPath("geo-seo", "geo-audit"),
|
|
1679
|
-
"references",
|
|
1680
|
-
briefFileName
|
|
1681
|
-
);
|
|
1682
|
-
}
|
|
1683
|
-
};
|
|
1684
|
-
}
|
|
1685
|
-
var SKILL_GROUPS = [
|
|
1686
|
-
{
|
|
1687
|
-
id: "essentials",
|
|
1688
|
-
label: "Essentials",
|
|
1689
|
-
description: "Web design and writing guidelines from Vercel Labs.",
|
|
1690
|
-
defaultSelected: true,
|
|
1691
|
-
skills: [
|
|
1692
|
-
pinnedSkill(ESSENTIALS_REPOSITORY, "web-design-guidelines"),
|
|
1693
|
-
pinnedSkill(ESSENTIALS_REPOSITORY, "writing-guidelines")
|
|
1694
|
-
]
|
|
1695
|
-
},
|
|
1696
|
-
{
|
|
1697
|
-
id: "design",
|
|
1698
|
-
label: "Design & UI/UX",
|
|
1699
|
-
description: "agemon-design: design engineering with anti-slop rules, discovery, and outcome recipes for dashboards, landings, and auth screens.",
|
|
1700
|
-
defaultSelected: false,
|
|
1701
|
-
skills: [
|
|
1702
|
-
vendoredSkill("design", "agemon-design"),
|
|
1703
|
-
vendoredSkill("design", "agemon-design-minimal"),
|
|
1704
|
-
vendoredSkill("design", "agemon-design-editorial"),
|
|
1705
|
-
vendoredSkill("design", "agemon-design-dashboard")
|
|
1706
|
-
]
|
|
1707
|
-
},
|
|
1708
|
-
{
|
|
1709
|
-
id: "security",
|
|
1710
|
-
label: "Security",
|
|
1711
|
-
description: "Exploit-driven security review \u2014 no finding without a working proof-of-concept, CVSS-aligned severity.",
|
|
1712
|
-
defaultSelected: false,
|
|
1713
|
-
skills: [vendoredSkill("security", "agemon-security")]
|
|
1714
|
-
},
|
|
1715
|
-
{
|
|
1716
|
-
id: "code-quality",
|
|
1717
|
-
label: "Code Quality",
|
|
1718
|
-
description: "Simplicity, DRY architecture, self-documenting naming, and surgical scope control for day-to-day edits.",
|
|
1719
|
-
defaultSelected: false,
|
|
1720
|
-
skills: [
|
|
1721
|
-
vendoredSkill("code-quality", "agemon-clean-code"),
|
|
1722
|
-
vendoredSkill("code-quality", "agemon-house-rules")
|
|
1723
|
-
]
|
|
1724
|
-
},
|
|
1725
|
-
{
|
|
1726
|
-
id: "architecture",
|
|
1727
|
-
label: "Code Architecture",
|
|
1728
|
-
description: "Clean Architecture review: dependency rule, layer separation, boundary crossing, SOLID.",
|
|
1729
|
-
defaultSelected: false,
|
|
1730
|
-
skills: [vendoredSkill("architecture", "agemon-architecture")]
|
|
1731
|
-
},
|
|
1732
|
-
{
|
|
1733
|
-
id: "self-review",
|
|
1734
|
-
label: "Self-Review",
|
|
1735
|
-
description: "Verification before claiming completion, giving and receiving code review, and root-cause-first debugging.",
|
|
1736
|
-
defaultSelected: false,
|
|
1737
|
-
skills: [
|
|
1738
|
-
vendoredSkill("self-review", "agemon-verify-before-done"),
|
|
1739
|
-
vendoredSkill("self-review", "agemon-review-intake"),
|
|
1740
|
-
vendoredSkill("self-review", "agemon-review-request"),
|
|
1741
|
-
vendoredSkill("self-review", "agemon-root-cause")
|
|
1742
|
-
]
|
|
1743
|
-
},
|
|
1744
|
-
{
|
|
1745
|
-
id: "performance",
|
|
1746
|
-
label: "Performance",
|
|
1747
|
-
description: "Algorithmic-complexity-first discipline: N+1 detection, hot-loop hygiene, and when not to optimize.",
|
|
1748
|
-
defaultSelected: false,
|
|
1749
|
-
skills: [vendoredSkill("performance", "agemon-performance")]
|
|
1750
|
-
},
|
|
1751
|
-
{
|
|
1752
|
-
id: "commit",
|
|
1753
|
-
label: "Commit Hygiene",
|
|
1754
|
-
description: "Staging review, commit message structure, and splitting unrelated changes into separate commits.",
|
|
1755
|
-
defaultSelected: false,
|
|
1756
|
-
skills: [vendoredSkill("commit", "agemon-commit")]
|
|
1757
|
-
},
|
|
1758
|
-
{
|
|
1759
|
-
id: "teamlead",
|
|
1760
|
-
label: "Team Lead",
|
|
1761
|
-
description: "Team-lead workflows: structured RFC planning and PRD generation for major features or architectural changes.",
|
|
1762
|
-
defaultSelected: false,
|
|
1763
|
-
skills: [
|
|
1764
|
-
vendoredSkill("team-lead", "agemon-plan-rfc"),
|
|
1765
|
-
vendoredSkill("team-lead", "prd-generator"),
|
|
1766
|
-
vendoredSkill("team-lead", "skill-headofit-audit"),
|
|
1767
|
-
vendoredSkill("team-lead", "skill-incident-rca"),
|
|
1768
|
-
vendoredSkill("team-lead", "skill-meeting-lifecycle"),
|
|
1769
|
-
vendoredSkill("team-lead", "skill-obsidian-vault-sync"),
|
|
1770
|
-
vendoredSkill("team-lead", "skill-prd-decomposer"),
|
|
1771
|
-
vendoredSkill("team-lead", "skill-sec-check"),
|
|
1772
|
-
vendoredSkill("team-lead", "skill-task-extractor"),
|
|
1773
|
-
vendoredSkill("team-lead", "skill-techlead-reviewer"),
|
|
1774
|
-
vendoredSkill("team-lead", "skill-tech-spike")
|
|
1775
|
-
]
|
|
1776
|
-
},
|
|
1777
|
-
{
|
|
1778
|
-
id: "geo-seo",
|
|
1779
|
-
label: "GEO / AI Search SEO",
|
|
1780
|
-
description: "Audit and optimize websites for AI search citation (ChatGPT, Perplexity, Google AI Overviews): citability, AI crawlers, llms.txt, schema, technical SEO, reports.",
|
|
1781
|
-
defaultSelected: false,
|
|
1782
|
-
skills: [
|
|
1783
|
-
vendoredSkill("geo-seo", "geo"),
|
|
1784
|
-
vendoredSkill("geo-seo", "geo-audit"),
|
|
1785
|
-
vendoredSkill("geo-seo", "geo-citability"),
|
|
1786
|
-
vendoredSkill("geo-seo", "geo-crawlers"),
|
|
1787
|
-
vendoredSkill("geo-seo", "geo-llmstxt"),
|
|
1788
|
-
vendoredSkill("geo-seo", "geo-brand-mentions"),
|
|
1789
|
-
vendoredSkill("geo-seo", "geo-platform-optimizer"),
|
|
1790
|
-
vendoredSkill("geo-seo", "geo-technical"),
|
|
1791
|
-
vendoredSkill("geo-seo", "geo-content"),
|
|
1792
|
-
vendoredSkill("geo-seo", "geo-report"),
|
|
1793
|
-
vendoredSkill("geo-seo", "geo-schema"),
|
|
1794
|
-
vendoredSkill("geo-seo", "geo-report-pdf")
|
|
1795
|
-
],
|
|
1796
|
-
agents: [
|
|
1797
|
-
geoAuditAgent(
|
|
1798
|
-
"geo-audit-ai-visibility",
|
|
1799
|
-
"ai-visibility.md",
|
|
1800
|
-
"Scores how quotable and visible a website is to AI search: citability, AI crawler access, llms.txt and brand presence.",
|
|
1801
|
-
["WebFetch"]
|
|
1802
|
-
),
|
|
1803
|
-
geoAuditAgent(
|
|
1804
|
-
"geo-audit-platform",
|
|
1805
|
-
"platform-analysis.md",
|
|
1806
|
-
"Scores a website's readiness for Google AI Overviews, ChatGPT, Perplexity, Gemini and Bing Copilot.",
|
|
1807
|
-
["WebFetch"]
|
|
1808
|
-
),
|
|
1809
|
-
geoAuditAgent(
|
|
1810
|
-
"geo-audit-technical",
|
|
1811
|
-
"technical.md",
|
|
1812
|
-
"Scores a website's technical health for AI crawlers: rendering, meta tags, headers, speed and security headers.",
|
|
1813
|
-
["WebFetch", "Bash"]
|
|
1814
|
-
),
|
|
1815
|
-
geoAuditAgent(
|
|
1816
|
-
"geo-audit-content",
|
|
1817
|
-
"content.md",
|
|
1818
|
-
"Scores a website's content quality and E-E-A-T signals: experience, expertise, authority and trust.",
|
|
1819
|
-
["WebFetch"]
|
|
1820
|
-
),
|
|
1821
|
-
geoAuditAgent(
|
|
1822
|
-
"geo-audit-schema",
|
|
1823
|
-
"schema.md",
|
|
1824
|
-
"Scores a website's schema.org structured data and finds missing GEO-relevant schema.",
|
|
1825
|
-
["WebFetch", "Bash"]
|
|
1826
|
-
)
|
|
1827
|
-
]
|
|
1828
|
-
}
|
|
1829
|
-
];
|
|
1830
|
-
var RETIRED_AGENT_NAMES = [];
|
|
1831
|
-
function findSkillGroup(groupId) {
|
|
1832
|
-
return SKILL_GROUPS.find((group) => group.id === groupId);
|
|
1833
|
-
}
|
|
1834
|
-
var CUSTOM_GROUP_DESCRIPTION = "Defined in this repository's agemon.toml, not by agemon.";
|
|
1835
|
-
function localSkill(path, skillName) {
|
|
1836
|
-
return {
|
|
1837
|
-
id: skillName,
|
|
1838
|
-
source: path,
|
|
1839
|
-
skillName,
|
|
1840
|
-
agent: "claude-code",
|
|
1841
|
-
localSourcePath: path
|
|
1842
|
-
};
|
|
1843
|
-
}
|
|
1844
|
-
function failCustomGroups(detail) {
|
|
1845
|
-
throw new Error(`agemon.toml is invalid: ${printable(detail)}`);
|
|
1846
|
-
}
|
|
1847
|
-
function buildCustomSkillGroups(configs) {
|
|
1848
|
-
const builtInSkillNames = new Set(
|
|
1849
|
-
SKILL_GROUPS.flatMap(
|
|
1850
|
-
(group) => group.skills.map((skill) => skill.skillName)
|
|
1851
|
-
)
|
|
1852
|
-
);
|
|
1853
|
-
return configs.map((config) => {
|
|
1854
|
-
if (findSkillGroup(config.id) !== void 0) {
|
|
1855
|
-
failCustomGroups(
|
|
1856
|
-
`custom_skill_groups.${config.id} uses the id of a built-in skill group`
|
|
1857
|
-
);
|
|
1858
|
-
}
|
|
1859
|
-
return {
|
|
1860
|
-
id: config.id,
|
|
1861
|
-
label: config.label,
|
|
1862
|
-
description: CUSTOM_GROUP_DESCRIPTION,
|
|
1863
|
-
defaultSelected: false,
|
|
1864
|
-
definedByRepository: true,
|
|
1865
|
-
skills: config.skills.map((skill) => {
|
|
1866
|
-
if (builtInSkillNames.has(skill.skillName)) {
|
|
1867
|
-
failCustomGroups(
|
|
1868
|
-
`custom_skill_groups.${config.id} names '${skill.skillName}', which is a built-in skill`
|
|
1869
|
-
);
|
|
1870
|
-
}
|
|
1871
|
-
return skill.kind === "local" ? localSkill(skill.path, skill.skillName) : pinnedSkill(
|
|
1872
|
-
{
|
|
1873
|
-
url: `https://github.com/${skill.owner}/${skill.repository}`,
|
|
1874
|
-
commit: skill.ref
|
|
1875
|
-
},
|
|
1876
|
-
skill.skillName
|
|
1877
|
-
);
|
|
1878
|
-
})
|
|
1879
|
-
};
|
|
1880
|
-
});
|
|
1881
|
-
}
|
|
1882
|
-
function assertCustomSkillGroupsAreValid(configs) {
|
|
1883
|
-
buildCustomSkillGroups(configs);
|
|
1884
|
-
}
|
|
1885
|
-
|
|
1886
|
-
// src/plugins/skills/skill-tree.ts
|
|
1887
|
-
import { constants as constants4 } from "fs";
|
|
1888
|
-
import { lstat as lstat4, open as open5, opendir } from "fs/promises";
|
|
1889
|
-
import { join as join6 } from "path";
|
|
1890
|
-
var MAX_SKILL_ENTRIES = 200;
|
|
1891
|
-
var MAX_SKILL_DEPTH = 8;
|
|
1892
|
-
var MAX_SKILL_BYTES = 8 * 1024 * 1024;
|
|
1893
|
-
var FINDER_METADATA_FILE = ".DS_Store";
|
|
1894
|
-
var SKILLS_CLI_COPY_EXCLUSIONS = {
|
|
1895
|
-
anyName: ["metadata.json"],
|
|
1896
|
-
directoryNames: [".git", "__pycache__", "__pypackages__"]
|
|
1897
|
-
};
|
|
1898
|
-
var SkillTreeRefusal = class extends Error {
|
|
1899
|
-
};
|
|
1900
|
-
var keepEveryEntry = () => false;
|
|
1901
|
-
function isLeftOutBySkillsCli(name, stats) {
|
|
1902
|
-
return SKILLS_CLI_COPY_EXCLUSIONS.anyName.includes(name) || stats.isDirectory() && SKILLS_CLI_COPY_EXCLUSIONS.directoryNames.includes(
|
|
1903
|
-
name
|
|
1904
|
-
);
|
|
1905
|
-
}
|
|
1906
|
-
function isFinderMetadataFile(name, stats) {
|
|
1907
|
-
return name === FINDER_METADATA_FILE && stats.isFile();
|
|
1908
|
-
}
|
|
1909
|
-
async function readRegularFileWithoutFollowing(path, maxBytes) {
|
|
1910
|
-
const handle = await open5(
|
|
1911
|
-
path,
|
|
1912
|
-
constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK
|
|
1913
|
-
);
|
|
1914
|
-
try {
|
|
1915
|
-
const stats = await handle.stat();
|
|
1916
|
-
if (!stats.isFile()) {
|
|
1917
|
-
return null;
|
|
1918
|
-
}
|
|
1919
|
-
if (stats.size > maxBytes) {
|
|
1920
|
-
throw new SkillTreeRefusal("it is larger than 8 MiB");
|
|
1921
|
-
}
|
|
1922
|
-
return await handle.readFile();
|
|
1923
|
-
} finally {
|
|
1924
|
-
await handle.close();
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
async function sortedNamesUpToCap(directory) {
|
|
1928
|
-
const names = [];
|
|
1929
|
-
for await (const entry of await opendir(directory)) {
|
|
1930
|
-
names.push(entry.name);
|
|
1931
|
-
if (names.length > MAX_SKILL_ENTRIES) {
|
|
1932
|
-
throw new SkillTreeRefusal(
|
|
1933
|
-
`it has more than ${MAX_SKILL_ENTRIES} entries`
|
|
1934
|
-
);
|
|
1517
|
+
get text() {
|
|
1518
|
+
return text;
|
|
1935
1519
|
}
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
async function runSubprocess(command, args, options = {}) {
|
|
1523
|
+
if (process.env.AGEMON_FAKE_SUBPROCESS === "1") {
|
|
1524
|
+
const { runFakeSubprocess } = await import("./fake-subprocess-IV4ML77S.js");
|
|
1525
|
+
return runFakeSubprocess(command, args, options);
|
|
1936
1526
|
}
|
|
1937
|
-
return
|
|
1527
|
+
return runRealSubprocess(command, args, options);
|
|
1938
1528
|
}
|
|
1939
|
-
async function
|
|
1940
|
-
const
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1529
|
+
async function runRealSubprocess(command, args, options = {}) {
|
|
1530
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_SUBPROCESS_TIMEOUT_MS;
|
|
1531
|
+
return await new Promise((resolve3) => {
|
|
1532
|
+
let settled = false;
|
|
1533
|
+
let timedOut = false;
|
|
1534
|
+
let timeoutHandle;
|
|
1535
|
+
let hardKillHandle;
|
|
1536
|
+
let drainHandle;
|
|
1537
|
+
const stdout = createBoundedCapture();
|
|
1538
|
+
const stderr = createBoundedCapture();
|
|
1539
|
+
const clearTimers = () => {
|
|
1540
|
+
clearTimeout(timeoutHandle);
|
|
1541
|
+
clearTimeout(hardKillHandle);
|
|
1542
|
+
clearTimeout(drainHandle);
|
|
1543
|
+
};
|
|
1544
|
+
const finalize = (result) => {
|
|
1545
|
+
if (settled) {
|
|
1546
|
+
return;
|
|
1956
1547
|
}
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1548
|
+
settled = true;
|
|
1549
|
+
clearTimers();
|
|
1550
|
+
resolve3(result);
|
|
1551
|
+
};
|
|
1552
|
+
const resultForExit = (code, signal) => {
|
|
1553
|
+
if (timedOut) {
|
|
1554
|
+
const timeoutMessage = `Command timed out after ${timeoutMs}ms.`;
|
|
1555
|
+
return {
|
|
1556
|
+
code: TIMEOUT_EXIT_CODE,
|
|
1557
|
+
stdout: stdout.text,
|
|
1558
|
+
stderr: stderr.text ? `${stderr.text}
|
|
1559
|
+
${timeoutMessage}` : timeoutMessage
|
|
1560
|
+
};
|
|
1961
1561
|
}
|
|
1962
|
-
if (
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1562
|
+
if (signal) {
|
|
1563
|
+
return {
|
|
1564
|
+
code: 1,
|
|
1565
|
+
stdout: stdout.text,
|
|
1566
|
+
stderr: `${stderr.text}Process terminated by signal: ${signal}`
|
|
1567
|
+
};
|
|
1966
1568
|
}
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
)
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
);
|
|
1569
|
+
return { code: code ?? 1, stdout: stdout.text, stderr: stderr.text };
|
|
1570
|
+
};
|
|
1571
|
+
const finalizeAfterDrainGrace = (code, signal) => {
|
|
1572
|
+
clearTimeout(drainHandle);
|
|
1573
|
+
drainHandle = setTimeout(() => {
|
|
1574
|
+
childProcess.stdout.destroy();
|
|
1575
|
+
childProcess.stderr.destroy();
|
|
1576
|
+
finalize(resultForExit(code, signal));
|
|
1577
|
+
}, STREAM_DRAIN_GRACE_MS);
|
|
1578
|
+
};
|
|
1579
|
+
const environment = {
|
|
1580
|
+
...agemonSubprocessEnvironment(),
|
|
1581
|
+
...options.env
|
|
1582
|
+
};
|
|
1583
|
+
for (const name of options.unsetEnv ?? []) {
|
|
1584
|
+
delete environment[name];
|
|
1585
|
+
}
|
|
1586
|
+
const childProcess = spawn(command, args, {
|
|
1587
|
+
cwd: options.cwd ?? process.cwd(),
|
|
1588
|
+
env: environment,
|
|
1589
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
1590
|
+
});
|
|
1591
|
+
if (timeoutMs > 0) {
|
|
1592
|
+
timeoutHandle = setTimeout(() => {
|
|
1593
|
+
timedOut = true;
|
|
1594
|
+
const signal = options.killSignal ?? "SIGTERM";
|
|
1595
|
+
const terminated = childProcess.kill(signal);
|
|
1596
|
+
if (!terminated) {
|
|
1597
|
+
finalize({
|
|
1598
|
+
code: TIMEOUT_EXIT_CODE,
|
|
1599
|
+
stdout: stdout.text,
|
|
1600
|
+
stderr: `${stderr.text}
|
|
1601
|
+
Command timed out after ${timeoutMs}ms and could not be signaled with ${signal}.`
|
|
1602
|
+
});
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
hardKillHandle = setTimeout(() => {
|
|
1606
|
+
childProcess.kill("SIGKILL");
|
|
1607
|
+
finalizeAfterDrainGrace(null, "SIGKILL");
|
|
1608
|
+
}, HARD_KILL_GRACE_MS);
|
|
1609
|
+
}, timeoutMs);
|
|
1610
|
+
}
|
|
1611
|
+
childProcess.stdout.setEncoding("utf8");
|
|
1612
|
+
childProcess.stderr.setEncoding("utf8");
|
|
1613
|
+
childProcess.stdout.on("data", (chunk) => stdout.append(chunk));
|
|
1614
|
+
childProcess.stderr.on("data", (chunk) => stderr.append(chunk));
|
|
1615
|
+
childProcess.on("error", (error) => {
|
|
1616
|
+
const errorMessage = stderr.text ? `${stderr.text}
|
|
1617
|
+
${SPAWN_ERROR_PREFIX}${error.message}` : `${SPAWN_ERROR_PREFIX}${error.message}`;
|
|
1618
|
+
finalize({ code: 1, stdout: stdout.text, stderr: errorMessage });
|
|
1619
|
+
});
|
|
1620
|
+
childProcess.on(
|
|
1621
|
+
"exit",
|
|
1622
|
+
(code, signal) => {
|
|
1623
|
+
clearTimeout(timeoutHandle);
|
|
1624
|
+
clearTimeout(hardKillHandle);
|
|
1625
|
+
finalizeAfterDrainGrace(code, signal);
|
|
1975
1626
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1627
|
+
);
|
|
1628
|
+
childProcess.on(
|
|
1629
|
+
"close",
|
|
1630
|
+
(code, signal) => {
|
|
1631
|
+
finalize(resultForExit(code, signal));
|
|
1979
1632
|
}
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
};
|
|
1983
|
-
await walk("", 1);
|
|
1984
|
-
return entries;
|
|
1985
|
-
}
|
|
1986
|
-
function fingerprintSkillTree(entries) {
|
|
1987
|
-
return fingerprintJson(
|
|
1988
|
-
entries.map((entry) => [
|
|
1989
|
-
entry.relativePath,
|
|
1990
|
-
entry.contents === null ? null : sha256Hex(entry.contents)
|
|
1991
|
-
])
|
|
1992
|
-
);
|
|
1993
|
-
}
|
|
1994
|
-
async function fingerprintSkillSource(directory) {
|
|
1995
|
-
return fingerprintSkillTree(
|
|
1996
|
-
await readSkillTree(directory, isLeftOutBySkillsCli)
|
|
1997
|
-
);
|
|
1998
|
-
}
|
|
1999
|
-
async function fingerprintInstalledSkill(directory) {
|
|
2000
|
-
return fingerprintSkillTree(
|
|
2001
|
-
await readSkillTree(directory, isFinderMetadataFile)
|
|
2002
|
-
);
|
|
1633
|
+
);
|
|
1634
|
+
});
|
|
2003
1635
|
}
|
|
2004
1636
|
|
|
2005
1637
|
// src/plugins/skills/skills-cli.ts
|
|
2006
|
-
import { existsSync as existsSync3 } from "fs";
|
|
2007
|
-
import {
|
|
2008
|
-
copyFile,
|
|
2009
|
-
mkdtemp,
|
|
2010
|
-
readdir,
|
|
2011
|
-
readFile as readFile3,
|
|
2012
|
-
rename as rename2,
|
|
2013
|
-
rm as rm4
|
|
2014
|
-
} from "fs/promises";
|
|
2015
|
-
import { join as join7 } from "path";
|
|
2016
1638
|
var TOOLS_LOCK_HASH_LENGTH = 16;
|
|
2017
1639
|
var TOOLS_INSTALL_TIMEOUT_MS = 18e4;
|
|
2018
1640
|
var TOOLS_LOCK_WAIT_MS = 10 * 6e4;
|
|
2019
1641
|
var TOOLS_MANIFEST_FILES = ["package.json", "package-lock.json"];
|
|
2020
|
-
var SKILLS_CLI_PATH_IN_TOOLS_DIR =
|
|
1642
|
+
var SKILLS_CLI_PATH_IN_TOOLS_DIR = join5(
|
|
2021
1643
|
"node_modules",
|
|
2022
1644
|
"skills",
|
|
2023
1645
|
"bin",
|
|
@@ -2042,19 +1664,19 @@ async function promoteStagingDirectory(stagingDirectory, toolsDirectory, cliPath
|
|
|
2042
1664
|
if (await renameUnlessAnotherRunWon(stagingDirectory, toolsDirectory)) {
|
|
2043
1665
|
return;
|
|
2044
1666
|
}
|
|
2045
|
-
if (
|
|
1667
|
+
if (existsSync2(cliPath)) {
|
|
2046
1668
|
return;
|
|
2047
1669
|
}
|
|
2048
1670
|
const brokenDirectory = `${stagingDirectory}.broken`;
|
|
2049
1671
|
await rename2(toolsDirectory, brokenDirectory);
|
|
2050
|
-
await
|
|
1672
|
+
await rm3(brokenDirectory, { recursive: true, force: true });
|
|
2051
1673
|
await renameUnlessAnotherRunWon(stagingDirectory, toolsDirectory);
|
|
2052
1674
|
}
|
|
2053
1675
|
var ABANDONED_TOOLS_DIRECTORY_PATTERN = /^[0-9a-f]{16}\.tmp-[^/]+$/;
|
|
2054
1676
|
async function removeAbandonedToolsDirectories(toolsRoot) {
|
|
2055
1677
|
for (const entry of await readdir(toolsRoot)) {
|
|
2056
1678
|
if (ABANDONED_TOOLS_DIRECTORY_PATTERN.test(entry)) {
|
|
2057
|
-
await
|
|
1679
|
+
await rm3(join5(toolsRoot, entry), { recursive: true, force: true });
|
|
2058
1680
|
}
|
|
2059
1681
|
}
|
|
2060
1682
|
}
|
|
@@ -2064,8 +1686,8 @@ async function installToolsDirectory(ctx, toolsRoot, manifestDirectory, toolsDir
|
|
|
2064
1686
|
try {
|
|
2065
1687
|
for (const fileName of TOOLS_MANIFEST_FILES) {
|
|
2066
1688
|
await copyFile(
|
|
2067
|
-
|
|
2068
|
-
|
|
1689
|
+
join5(manifestDirectory, fileName),
|
|
1690
|
+
join5(stagingDirectory, fileName)
|
|
2069
1691
|
);
|
|
2070
1692
|
}
|
|
2071
1693
|
const installResult = await ctx.run(
|
|
@@ -2087,24 +1709,24 @@ async function installToolsDirectory(ctx, toolsRoot, manifestDirectory, toolsDir
|
|
|
2087
1709
|
}
|
|
2088
1710
|
await promoteStagingDirectory(stagingDirectory, toolsDirectory, cliPath);
|
|
2089
1711
|
} finally {
|
|
2090
|
-
await
|
|
1712
|
+
await rm3(stagingDirectory, { recursive: true, force: true });
|
|
2091
1713
|
}
|
|
2092
1714
|
}
|
|
2093
1715
|
async function ensureSkillsCli(ctx) {
|
|
2094
1716
|
const manifestDirectory = resolveToolsManifestDirectory();
|
|
2095
1717
|
const lockHash = sha256Hex(
|
|
2096
|
-
await readFile3(
|
|
1718
|
+
await readFile3(join5(manifestDirectory, "package-lock.json"))
|
|
2097
1719
|
).slice(0, TOOLS_LOCK_HASH_LENGTH);
|
|
2098
1720
|
const toolsRoot = await prepareToolsRoot();
|
|
2099
|
-
const toolsDirectory =
|
|
2100
|
-
const cliPath =
|
|
2101
|
-
if (
|
|
1721
|
+
const toolsDirectory = join5(toolsRoot, lockHash);
|
|
1722
|
+
const cliPath = join5(toolsDirectory, SKILLS_CLI_PATH_IN_TOOLS_DIR);
|
|
1723
|
+
if (existsSync2(cliPath)) {
|
|
2102
1724
|
return cliPath;
|
|
2103
1725
|
}
|
|
2104
1726
|
await withAgemonStateLock(
|
|
2105
1727
|
"tools.lock",
|
|
2106
1728
|
async () => {
|
|
2107
|
-
if (!
|
|
1729
|
+
if (!existsSync2(cliPath)) {
|
|
2108
1730
|
await installToolsDirectory(
|
|
2109
1731
|
ctx,
|
|
2110
1732
|
toolsRoot,
|
|
@@ -2127,7 +1749,7 @@ async function runSkillsCli(ctx, args, timeoutMs) {
|
|
|
2127
1749
|
}
|
|
2128
1750
|
|
|
2129
1751
|
// src/core/config.ts
|
|
2130
|
-
import { join as
|
|
1752
|
+
import { join as join7, relative as relative2 } from "path";
|
|
2131
1753
|
import { isDeepStrictEqual } from "util";
|
|
2132
1754
|
|
|
2133
1755
|
// node_modules/smol-toml/dist/error.js
|
|
@@ -3072,11 +2694,11 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false, strictTemporal
|
|
|
3072
2694
|
}
|
|
3073
2695
|
|
|
3074
2696
|
// src/core/backups.ts
|
|
3075
|
-
import { dirname as dirname4, isAbsolute as isAbsolute5, join as
|
|
2697
|
+
import { dirname as dirname4, isAbsolute as isAbsolute5, join as join6, resolve as resolve2 } from "path";
|
|
3076
2698
|
var BACKUP_SEGMENTS = ["backups"];
|
|
3077
2699
|
var V1_BACKUP_SEGMENTS = ["backups", "master-prompt"];
|
|
3078
|
-
var BACKUP_DIRECTORY =
|
|
3079
|
-
var V1_BACKUP_DIRECTORY =
|
|
2700
|
+
var BACKUP_DIRECTORY = join6(AGEMON_STATE_DIRECTORY, ...BACKUP_SEGMENTS);
|
|
2701
|
+
var V1_BACKUP_DIRECTORY = join6(AGEMON_STATE_DIRECTORY, ...V1_BACKUP_SEGMENTS);
|
|
3080
2702
|
var RESOURCE_ID_HASH_LENGTH = 12;
|
|
3081
2703
|
function sanitizeForFileName(value) {
|
|
3082
2704
|
return value.replace(/[^a-zA-Z0-9._-]/gu, "_");
|
|
@@ -3086,24 +2708,24 @@ function resolveImmutableBackupPath(cwd, resourceId) {
|
|
|
3086
2708
|
0,
|
|
3087
2709
|
RESOURCE_ID_HASH_LENGTH
|
|
3088
2710
|
);
|
|
3089
|
-
return
|
|
2711
|
+
return join6(
|
|
3090
2712
|
cwd,
|
|
3091
2713
|
BACKUP_DIRECTORY,
|
|
3092
2714
|
`${sanitizeForFileName(resourceId)}-${resourceIdHash}.bak`
|
|
3093
2715
|
);
|
|
3094
2716
|
}
|
|
3095
2717
|
function resolveLegacyBackupPath(cwd, resourceId) {
|
|
3096
|
-
return
|
|
2718
|
+
return join6(cwd, BACKUP_DIRECTORY, `${sanitizeForFileName(resourceId)}.bak`);
|
|
3097
2719
|
}
|
|
3098
2720
|
function resolveV1RuleFileBackupPath(cwd, target) {
|
|
3099
|
-
return
|
|
2721
|
+
return join6(cwd, V1_BACKUP_DIRECTORY, `${sanitizeForFileName(target)}.bak`);
|
|
3100
2722
|
}
|
|
3101
2723
|
function backupDirectorySegments(cwd, backupPath) {
|
|
3102
2724
|
const directory = dirname4(backupPath);
|
|
3103
|
-
if (directory ===
|
|
2725
|
+
if (directory === join6(cwd, BACKUP_DIRECTORY)) {
|
|
3104
2726
|
return BACKUP_SEGMENTS;
|
|
3105
2727
|
}
|
|
3106
|
-
if (directory ===
|
|
2728
|
+
if (directory === join6(cwd, V1_BACKUP_DIRECTORY)) {
|
|
3107
2729
|
return V1_BACKUP_SEGMENTS;
|
|
3108
2730
|
}
|
|
3109
2731
|
return null;
|
|
@@ -3301,7 +2923,7 @@ var LOCAL_SKILL_KEYS = keyNames(
|
|
|
3301
2923
|
AGEMON_TOML_TABLES.customSkill.keys.filter((key) => !key.githubSourceOnly)
|
|
3302
2924
|
);
|
|
3303
2925
|
function resolveConfigPath(cwd) {
|
|
3304
|
-
return
|
|
2926
|
+
return join7(cwd, CONFIG_FILE_NAME);
|
|
3305
2927
|
}
|
|
3306
2928
|
function fail(detail) {
|
|
3307
2929
|
throw new Error(`${CONFIG_FILE_NAME} is invalid: ${printable(detail)}`);
|
|
@@ -3630,8 +3252,8 @@ async function writeConfig(cwd, config) {
|
|
|
3630
3252
|
}
|
|
3631
3253
|
|
|
3632
3254
|
// src/plugins/skills/skills-cli-targets.ts
|
|
3633
|
-
import { lstat as lstat5, rm as
|
|
3634
|
-
import { join as
|
|
3255
|
+
import { lstat as lstat5, rm as rm4, unlink } from "fs/promises";
|
|
3256
|
+
import { join as join8 } from "path";
|
|
3635
3257
|
var CANONICAL_SKILLS_DIRECTORY = ".agents/skills";
|
|
3636
3258
|
var CLAUDE_SKILLS_DIRECTORY = ".claude/skills";
|
|
3637
3259
|
var SKILLS_LOCK_FILE = "skills-lock.json";
|
|
@@ -3666,13 +3288,13 @@ async function prepareSkillsCliTargets(repoRoot, skillNames) {
|
|
|
3666
3288
|
);
|
|
3667
3289
|
if (canonicalDirectory !== null) {
|
|
3668
3290
|
for (const skillName of skillNames) {
|
|
3669
|
-
const stats = await lstatIfPresent(
|
|
3291
|
+
const stats = await lstatIfPresent(join8(canonicalDirectory, skillName));
|
|
3670
3292
|
if (stats?.isSymbolicLink()) {
|
|
3671
3293
|
refuse(`${CANONICAL_SKILLS_DIRECTORY}/${skillName}`, "is a symlink");
|
|
3672
3294
|
}
|
|
3673
3295
|
}
|
|
3674
3296
|
}
|
|
3675
|
-
const lockStats = await lstatIfPresent(
|
|
3297
|
+
const lockStats = await lstatIfPresent(join8(repoRoot, SKILLS_LOCK_FILE));
|
|
3676
3298
|
if (lockStats !== null && !lockStats.isFile()) {
|
|
3677
3299
|
refuse(SKILLS_LOCK_FILE, "is a symlink or not a regular file");
|
|
3678
3300
|
}
|
|
@@ -3687,192 +3309,13 @@ async function removeInstalledSkillCopy(repoRoot, skillName) {
|
|
|
3687
3309
|
if (skillsDirectory === null) {
|
|
3688
3310
|
return;
|
|
3689
3311
|
}
|
|
3690
|
-
const copyPath =
|
|
3312
|
+
const copyPath = join8(skillsDirectory, skillName);
|
|
3691
3313
|
const stats = await lstatIfPresent(copyPath);
|
|
3692
3314
|
if (stats?.isSymbolicLink()) {
|
|
3693
3315
|
await unlink(copyPath);
|
|
3694
3316
|
} else if (stats !== null) {
|
|
3695
|
-
await
|
|
3696
|
-
}
|
|
3697
|
-
}
|
|
3698
|
-
|
|
3699
|
-
// src/core/install-method.ts
|
|
3700
|
-
import { existsSync as existsSync4, readFileSync as readFileSync2, realpathSync } from "fs";
|
|
3701
|
-
import { lstat as lstat7, realpath as realpath4 } from "fs/promises";
|
|
3702
|
-
import { basename, dirname as dirname5, join as join11, sep as sep2 } from "path";
|
|
3703
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3704
|
-
|
|
3705
|
-
// src/core/npm-global.ts
|
|
3706
|
-
import { lstat as lstat6, stat as stat2 } from "fs/promises";
|
|
3707
|
-
import { isAbsolute as isAbsolute6, resolve as resolve3 } from "path";
|
|
3708
|
-
var NPM_ROOT_TIMEOUT_MS = 2e4;
|
|
3709
|
-
async function isDirectory(path) {
|
|
3710
|
-
try {
|
|
3711
|
-
return (await stat2(path)).isDirectory();
|
|
3712
|
-
} catch {
|
|
3713
|
-
return false;
|
|
3714
|
-
}
|
|
3715
|
-
}
|
|
3716
|
-
async function pathIsMissing(path) {
|
|
3717
|
-
try {
|
|
3718
|
-
await lstat6(path);
|
|
3719
|
-
return false;
|
|
3720
|
-
} catch (error) {
|
|
3721
|
-
return error.code === "ENOENT";
|
|
3722
|
-
}
|
|
3723
|
-
}
|
|
3724
|
-
async function resolveGlobalNpmRoot(run, options = {}) {
|
|
3725
|
-
const npmRootResult = await run("npm", ["root", "--global"], {
|
|
3726
|
-
timeoutMs: NPM_ROOT_TIMEOUT_MS,
|
|
3727
|
-
cwd: options.cwd
|
|
3728
|
-
});
|
|
3729
|
-
if (npmRootResult.code !== 0) {
|
|
3730
|
-
throw new Error(
|
|
3731
|
-
`npm root --global failed: ${describeSubprocessFailure(npmRootResult, "npm")}`
|
|
3732
|
-
);
|
|
3733
|
-
}
|
|
3734
|
-
const npmRoot = npmRootResult.stdout.trim();
|
|
3735
|
-
if (!isAbsolute6(npmRoot)) {
|
|
3736
|
-
throw new Error(
|
|
3737
|
-
`npm root --global returned ${printable(npmRoot)}, which is not an absolute path.`
|
|
3738
|
-
);
|
|
3739
|
-
}
|
|
3740
|
-
if (resolve3(npmRoot) !== npmRoot || !isSafeIdentifier(npmRoot)) {
|
|
3741
|
-
throw new Error(
|
|
3742
|
-
`npm root --global returned ${printable(npmRoot)}, which is not a single normalised path.`
|
|
3743
|
-
);
|
|
3744
|
-
}
|
|
3745
|
-
if (options.mayNotExistYet && await pathIsMissing(npmRoot)) {
|
|
3746
|
-
return npmRoot;
|
|
3317
|
+
await rm4(copyPath, { recursive: true, force: true });
|
|
3747
3318
|
}
|
|
3748
|
-
if (!await isDirectory(npmRoot)) {
|
|
3749
|
-
throw new Error(
|
|
3750
|
-
`npm root --global returned ${printable(npmRoot)}, which is not a directory. npm masks UUID-like path segments as ***; use an npm prefix without one.`
|
|
3751
|
-
);
|
|
3752
|
-
}
|
|
3753
|
-
return npmRoot;
|
|
3754
|
-
}
|
|
3755
|
-
|
|
3756
|
-
// src/core/install-method.ts
|
|
3757
|
-
var PACKAGE_NAME2 = "agemon";
|
|
3758
|
-
var PACKAGE_JSON_SEARCH_DEPTH = 5;
|
|
3759
|
-
var INSTALL_MARKER_FILE_NAME = ".agemon-install";
|
|
3760
|
-
var SOURCE_CHECKOUT_ENTRIES = [".git", "src"];
|
|
3761
|
-
var NPX_CACHE_SEGMENT = "_npx";
|
|
3762
|
-
function readPackageName2(directory) {
|
|
3763
|
-
try {
|
|
3764
|
-
const manifest = JSON.parse(
|
|
3765
|
-
readFileSync2(join11(directory, "package.json"), "utf8")
|
|
3766
|
-
);
|
|
3767
|
-
return manifest.name;
|
|
3768
|
-
} catch {
|
|
3769
|
-
return void 0;
|
|
3770
|
-
}
|
|
3771
|
-
}
|
|
3772
|
-
function resolvePackageRoot2(fromDirectory = dirname5(fileURLToPath2(import.meta.url))) {
|
|
3773
|
-
let directory = fromDirectory;
|
|
3774
|
-
for (let depth = 0; depth < PACKAGE_JSON_SEARCH_DEPTH; depth += 1) {
|
|
3775
|
-
if (readPackageName2(directory) === PACKAGE_NAME2) {
|
|
3776
|
-
return realpathSync(directory);
|
|
3777
|
-
}
|
|
3778
|
-
directory = dirname5(directory);
|
|
3779
|
-
}
|
|
3780
|
-
throw new Error("Unable to locate agemon's package.json.");
|
|
3781
|
-
}
|
|
3782
|
-
function readPackageVersion(packageRoot = resolvePackageRoot2()) {
|
|
3783
|
-
const manifest = JSON.parse(
|
|
3784
|
-
readFileSync2(join11(packageRoot, "package.json"), "utf8")
|
|
3785
|
-
);
|
|
3786
|
-
return manifest.version;
|
|
3787
|
-
}
|
|
3788
|
-
function isSourceCheckout(packageRoot) {
|
|
3789
|
-
return SOURCE_CHECKOUT_ENTRIES.some(
|
|
3790
|
-
(entry) => existsSync4(join11(packageRoot, entry))
|
|
3791
|
-
);
|
|
3792
|
-
}
|
|
3793
|
-
async function hasRegularInstallMarker(packageRoot) {
|
|
3794
|
-
try {
|
|
3795
|
-
return (await lstat7(join11(packageRoot, INSTALL_MARKER_FILE_NAME))).isFile();
|
|
3796
|
-
} catch {
|
|
3797
|
-
return false;
|
|
3798
|
-
}
|
|
3799
|
-
}
|
|
3800
|
-
function isInsideNodeModules(packageRoot) {
|
|
3801
|
-
return basename(dirname5(packageRoot)) === "node_modules";
|
|
3802
|
-
}
|
|
3803
|
-
async function resolveGlobalNpmPrefix(packageRoot, run) {
|
|
3804
|
-
try {
|
|
3805
|
-
const globalRoot = await realpath4(await resolveGlobalNpmRoot(run));
|
|
3806
|
-
const globalRootHoldsThisCopy = globalRoot === dirname5(packageRoot);
|
|
3807
|
-
const globalRootIsPrefixLib = basename(dirname5(globalRoot)) === "lib";
|
|
3808
|
-
return globalRootHoldsThisCopy && globalRootIsPrefixLib ? dirname5(dirname5(globalRoot)) : void 0;
|
|
3809
|
-
} catch {
|
|
3810
|
-
return void 0;
|
|
3811
|
-
}
|
|
3812
|
-
}
|
|
3813
|
-
async function resolveInstallMethod(options = {}) {
|
|
3814
|
-
const packageRoot = options.packageRoot ?? resolvePackageRoot2();
|
|
3815
|
-
if (isSourceCheckout(packageRoot)) {
|
|
3816
|
-
return { kind: "dev" };
|
|
3817
|
-
}
|
|
3818
|
-
if (await hasRegularInstallMarker(packageRoot)) {
|
|
3819
|
-
return { kind: "install-script", installDir: packageRoot };
|
|
3820
|
-
}
|
|
3821
|
-
if (packageRoot.split(sep2).includes(NPX_CACHE_SEGMENT)) {
|
|
3822
|
-
return { kind: "npx" };
|
|
3823
|
-
}
|
|
3824
|
-
if (isInsideNodeModules(packageRoot)) {
|
|
3825
|
-
const prefix = await resolveGlobalNpmPrefix(
|
|
3826
|
-
packageRoot,
|
|
3827
|
-
options.run ?? runSubprocess
|
|
3828
|
-
);
|
|
3829
|
-
if (prefix !== void 0) {
|
|
3830
|
-
return { kind: "npm-global", packageRoot, prefix };
|
|
3831
|
-
}
|
|
3832
|
-
}
|
|
3833
|
-
return { kind: "unknown", packageRoot };
|
|
3834
|
-
}
|
|
3835
|
-
|
|
3836
|
-
// src/core/dev-mode.ts
|
|
3837
|
-
var FAKE_BACKEND_ENV_VARS = [
|
|
3838
|
-
"AGEMON_FAKE_SUBPROCESS",
|
|
3839
|
-
"AGEMON_FAKE_SERVICES"
|
|
3840
|
-
];
|
|
3841
|
-
function isDevMode(packageRoot) {
|
|
3842
|
-
return process.env.AGEMON_DEV === "1" && isSourceCheckout(packageRoot ?? resolvePackageRoot2());
|
|
3843
|
-
}
|
|
3844
|
-
function assertFakeBackendsAreDevOnly(packageRoot) {
|
|
3845
|
-
const activeFakeVars = FAKE_BACKEND_ENV_VARS.filter(
|
|
3846
|
-
(name) => process.env[name] === "1"
|
|
3847
|
-
);
|
|
3848
|
-
if (activeFakeVars.length > 0 && !isDevMode(packageRoot)) {
|
|
3849
|
-
throw new Error(
|
|
3850
|
-
`${activeFakeVars.join(", ")} must never be set outside the sandbox harness \u2014 refusing to start.`
|
|
3851
|
-
);
|
|
3852
|
-
}
|
|
3853
|
-
}
|
|
3854
|
-
|
|
3855
|
-
// src/core/fake-pinned-skills.ts
|
|
3856
|
-
var FAKE_PINNED_SKILL_MANIFEST_FILE = "SKILL.md";
|
|
3857
|
-
function fakePinnedSkillManifest(skillName) {
|
|
3858
|
-
return `---
|
|
3859
|
-
name: ${skillName}
|
|
3860
|
-
description: Stand-in for the pinned ${skillName} skill, written by agemon's fake git backend.
|
|
3861
|
-
---
|
|
3862
|
-
|
|
3863
|
-
Fake ${skillName}.
|
|
3864
|
-
`;
|
|
3865
|
-
}
|
|
3866
|
-
function fakePinnedSkillFingerprint(skillName) {
|
|
3867
|
-
return fingerprintSkillTree([
|
|
3868
|
-
{
|
|
3869
|
-
relativePath: FAKE_PINNED_SKILL_MANIFEST_FILE,
|
|
3870
|
-
contents: Buffer.from(fakePinnedSkillManifest(skillName))
|
|
3871
|
-
}
|
|
3872
|
-
]);
|
|
3873
|
-
}
|
|
3874
|
-
function fakeSubprocessesActive() {
|
|
3875
|
-
return process.env.AGEMON_FAKE_SUBPROCESS === "1" && isDevMode();
|
|
3876
3319
|
}
|
|
3877
3320
|
|
|
3878
3321
|
export {
|
|
@@ -3910,17 +3353,24 @@ export {
|
|
|
3910
3353
|
containsHomeDirectory,
|
|
3911
3354
|
CODE_REVIEW_GRAPH_VERSION,
|
|
3912
3355
|
CODE_REVIEW_GRAPH_PACKAGE_SPEC,
|
|
3913
|
-
ESSENTIALS_SKILLS_COMMIT,
|
|
3914
3356
|
AGNIX_VERSION,
|
|
3915
3357
|
AGNIX_RELEASE_ARCHIVE_SHA256,
|
|
3916
3358
|
AGNIX_NPM_TARBALL,
|
|
3917
3359
|
AGNIX_PACKAGE_FILE_SHA256,
|
|
3918
3360
|
AGNIX_BINARY_SHA256,
|
|
3919
|
-
resolveToolsManifestDirectory,
|
|
3920
|
-
withFileLock,
|
|
3921
3361
|
sha256Hex,
|
|
3922
3362
|
fingerprintJson,
|
|
3923
3363
|
fingerprintContent,
|
|
3364
|
+
SkillTreeRefusal,
|
|
3365
|
+
isLeftOutBySkillsCli,
|
|
3366
|
+
readSkillTree,
|
|
3367
|
+
fingerprintSkillTree,
|
|
3368
|
+
fingerprintSkillSource,
|
|
3369
|
+
readInstalledSkill,
|
|
3370
|
+
fingerprintInstalledSkill,
|
|
3371
|
+
resolveVendoredSkillPath,
|
|
3372
|
+
resolveToolsManifestDirectory,
|
|
3373
|
+
withFileLock,
|
|
3924
3374
|
resolveStateRoot,
|
|
3925
3375
|
resolveAgemonStateDirectory,
|
|
3926
3376
|
checkAgemonStateDirectoryBeforeRun,
|
|
@@ -3929,21 +3379,6 @@ export {
|
|
|
3929
3379
|
repositoryStateKey,
|
|
3930
3380
|
withAgemonStateLock,
|
|
3931
3381
|
withRepositoryRunLock,
|
|
3932
|
-
isPristinePinnedCheckout,
|
|
3933
|
-
skillPathInRepository,
|
|
3934
|
-
resolvePinnedSkillPath,
|
|
3935
|
-
fetchPinnedSkillsSource,
|
|
3936
|
-
SKILL_GROUPS,
|
|
3937
|
-
RETIRED_AGENT_NAMES,
|
|
3938
|
-
findSkillGroup,
|
|
3939
|
-
buildCustomSkillGroups,
|
|
3940
|
-
assertCustomSkillGroupsAreValid,
|
|
3941
|
-
SkillTreeRefusal,
|
|
3942
|
-
isLeftOutBySkillsCli,
|
|
3943
|
-
readSkillTree,
|
|
3944
|
-
fingerprintSkillTree,
|
|
3945
|
-
fingerprintSkillSource,
|
|
3946
|
-
fingerprintInstalledSkill,
|
|
3947
3382
|
SKILLS_CLI_PATH_IN_TOOLS_DIR,
|
|
3948
3383
|
runSkillsCli,
|
|
3949
3384
|
resolveImmutableBackupPath,
|
|
@@ -3963,16 +3398,6 @@ export {
|
|
|
3963
3398
|
SKILLS_LOCK_FILE,
|
|
3964
3399
|
prepareSkillsCliTargets,
|
|
3965
3400
|
removeInstalledSkillCopy,
|
|
3966
|
-
resolveGlobalNpmRoot,
|
|
3967
|
-
INSTALL_MARKER_FILE_NAME,
|
|
3968
|
-
readPackageVersion,
|
|
3969
|
-
resolveInstallMethod,
|
|
3970
|
-
isDevMode,
|
|
3971
|
-
assertFakeBackendsAreDevOnly,
|
|
3972
|
-
FAKE_PINNED_SKILL_MANIFEST_FILE,
|
|
3973
|
-
fakePinnedSkillManifest,
|
|
3974
|
-
fakePinnedSkillFingerprint,
|
|
3975
|
-
fakeSubprocessesActive,
|
|
3976
3401
|
MAX_RAW_OUTPUT_LINE_CHARACTERS,
|
|
3977
3402
|
sanitizeOutput,
|
|
3978
3403
|
capShownLine,
|
|
@@ -4023,4 +3448,4 @@ smol-toml/dist/index.js:
|
|
|
4023
3448
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
4024
3449
|
*)
|
|
4025
3450
|
*/
|
|
4026
|
-
//# sourceMappingURL=chunk-
|
|
3451
|
+
//# sourceMappingURL=chunk-ZZBF3GOV.js.map
|