@kody-ade/kody-engine 0.4.506 → 0.4.508

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/kody.js CHANGED
@@ -15,7 +15,7 @@ var init_package = __esm({
15
15
  "package.json"() {
16
16
  package_default = {
17
17
  name: "@kody-ade/kody-engine",
18
- version: "0.4.506",
18
+ version: "0.4.508",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -618,6 +618,12 @@ function formatResult(msg) {
618
618
  === ${tag}${dur}${turns}${cost} ===`;
619
619
  }
620
620
  function summarizeToolInput(toolName, input = {}) {
621
+ if (toolName === "Agent") {
622
+ const agent = summarizeSingleLineValue(input.subagent_type, "unknown", 80);
623
+ const requestedModel = summarizeSingleLineValue(input.model, "inherit", 80);
624
+ const ignoredOverride = requestedModel === "inherit" ? "" : ` (ignored override=${requestedModel})`;
625
+ return `: ${agent} model=inherit${ignoredOverride}`;
626
+ }
621
627
  if (toolName === "Bash" && typeof input.command === "string") {
622
628
  const cmd = input.command.split("\n")[0];
623
629
  return `: ${truncate(cmd, 120)}`;
@@ -630,6 +636,10 @@ function summarizeToolInput(toolName, input = {}) {
630
636
  }
631
637
  return "";
632
638
  }
639
+ function summarizeSingleLineValue(value, fallback, max) {
640
+ if (typeof value !== "string" || value.trim() === "") return fallback;
641
+ return truncate(value.trim().split(/\r?\n/, 1)[0], max);
642
+ }
633
643
  function stringifyToolContent(content) {
634
644
  if (typeof content === "string") return content;
635
645
  if (Array.isArray(content)) {
@@ -689,6 +699,178 @@ var init_runtimePaths = __esm({
689
699
  }
690
700
  });
691
701
 
702
+ // src/scripts/buildSyntheticPlugin.ts
703
+ import * as fs3 from "fs";
704
+ import * as os3 from "os";
705
+ import * as path4 from "path";
706
+ function getPluginsCatalogRoot() {
707
+ const here = path4.dirname(new URL(import.meta.url).pathname);
708
+ const candidates = [
709
+ path4.join(here, "..", "plugins"),
710
+ // dev: src/scripts → src/plugins
711
+ path4.join(here, "..", "..", "plugins"),
712
+ // built: dist/scripts → dist/plugins
713
+ path4.join(here, "..", "..", "src", "plugins")
714
+ // fallback
715
+ ];
716
+ for (const c of candidates) {
717
+ if (fs3.existsSync(c) && fs3.statSync(c).isDirectory()) return c;
718
+ }
719
+ return candidates[0];
720
+ }
721
+ function copyDir(src, dst) {
722
+ fs3.mkdirSync(dst, { recursive: true });
723
+ for (const ent of fs3.readdirSync(src, { withFileTypes: true })) {
724
+ const s = path4.join(src, ent.name);
725
+ const d = path4.join(dst, ent.name);
726
+ if (ent.isDirectory()) copyDir(s, d);
727
+ else if (ent.isFile()) fs3.copyFileSync(s, d);
728
+ }
729
+ }
730
+ var buildSyntheticPlugin;
731
+ var init_buildSyntheticPlugin = __esm({
732
+ "src/scripts/buildSyntheticPlugin.ts"() {
733
+ "use strict";
734
+ buildSyntheticPlugin = async (ctx, profile) => {
735
+ const cc = profile.claudeCode;
736
+ const needsSynthetic = cc.skills.length > 0 || cc.commands.length > 0 || cc.hooks.length > 0;
737
+ if (!needsSynthetic) return;
738
+ const catalog = getPluginsCatalogRoot();
739
+ const runId = `${profile.name}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
740
+ const root = path4.join(os3.tmpdir(), `kody-synth-${runId}`);
741
+ fs3.mkdirSync(path4.join(root, ".claude-plugin"), { recursive: true });
742
+ const resolvePart = (bucket, entry) => {
743
+ const local = path4.join(profile.dir, bucket, entry);
744
+ if (fs3.existsSync(local)) return local;
745
+ const shared = path4.resolve(profile.dir, "..", "..", "shared", bucket, entry);
746
+ if (fs3.existsSync(shared)) return shared;
747
+ const central = path4.join(catalog, bucket, entry);
748
+ if (fs3.existsSync(central)) return central;
749
+ throw new Error(
750
+ `buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${path4.dirname(shared)}/), or catalog (${catalog}/${bucket}/)`
751
+ );
752
+ };
753
+ if (cc.skills.length > 0) {
754
+ const dst = path4.join(root, "skills");
755
+ fs3.mkdirSync(dst, { recursive: true });
756
+ for (const name of cc.skills) {
757
+ copyDir(resolvePart("skills", name), path4.join(dst, name));
758
+ }
759
+ }
760
+ if (cc.commands.length > 0) {
761
+ const dst = path4.join(root, "commands");
762
+ fs3.mkdirSync(dst, { recursive: true });
763
+ for (const name of cc.commands) {
764
+ fs3.copyFileSync(resolvePart("commands", `${name}.md`), path4.join(dst, `${name}.md`));
765
+ }
766
+ }
767
+ if (cc.hooks.length > 0) {
768
+ const dst = path4.join(root, "hooks");
769
+ fs3.mkdirSync(dst, { recursive: true });
770
+ const merged = { hooks: {} };
771
+ for (const name of cc.hooks) {
772
+ const src = resolvePart("hooks", `${name}.json`);
773
+ const parsed = JSON.parse(fs3.readFileSync(src, "utf-8"));
774
+ for (const [event, entries] of Object.entries(parsed.hooks ?? {})) {
775
+ if (!Array.isArray(entries)) continue;
776
+ if (!merged.hooks[event]) merged.hooks[event] = [];
777
+ merged.hooks[event].push(...entries);
778
+ }
779
+ }
780
+ fs3.writeFileSync(path4.join(dst, "hooks.json"), `${JSON.stringify(merged, null, 2)}
781
+ `);
782
+ }
783
+ const manifest = {
784
+ name: `kody-synth-${profile.name}`,
785
+ version: "1.0.0",
786
+ description: `Synthetic plugin assembled by Kody for profile '${profile.name}' at runtime.`
787
+ };
788
+ if (cc.skills.length > 0) manifest.skills = ["./skills/"];
789
+ if (cc.commands.length > 0) manifest.commands = ["./commands/"];
790
+ fs3.writeFileSync(path4.join(root, ".claude-plugin", "plugin.json"), `${JSON.stringify(manifest, null, 2)}
791
+ `);
792
+ ctx.data.syntheticPluginPath = root;
793
+ };
794
+ }
795
+ });
796
+
797
+ // src/subagents.ts
798
+ import * as fs4 from "fs";
799
+ import * as path5 from "path";
800
+ async function enforceSubagentModelInheritance(input) {
801
+ const toolInput = input.tool_input;
802
+ if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
803
+ const updatedInput = { ...toolInput };
804
+ delete updatedInput.model;
805
+ return {
806
+ hookSpecificOutput: {
807
+ hookEventName: "PreToolUse",
808
+ updatedInput
809
+ }
810
+ };
811
+ }
812
+ function splitFrontmatter(raw) {
813
+ const match = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(raw);
814
+ if (!match) return { fm: {}, body: raw.trim() };
815
+ const fm = {};
816
+ for (const line of match[1].split("\n")) {
817
+ const idx = line.indexOf(":");
818
+ if (idx === -1) continue;
819
+ fm[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
820
+ }
821
+ return { fm, body: (match[2] ?? "").trim() };
822
+ }
823
+ function resolveAgentFile(profileDir, name) {
824
+ const local = path5.join(profileDir, "agents", `${name}.md`);
825
+ if (fs4.existsSync(local)) return local;
826
+ const shared = path5.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
827
+ if (fs4.existsSync(shared)) return shared;
828
+ const central = path5.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
829
+ if (fs4.existsSync(central)) return central;
830
+ throw new Error(
831
+ `loadSubagents: agent '${name}' not found in ${profileDir}/agents/, hydrated shared assets, or engine catalog`
832
+ );
833
+ }
834
+ function captureSubagentTemplates(profile) {
835
+ const names = profile.claudeCode.subagents;
836
+ if (!names || names.length === 0) return {};
837
+ const out = {};
838
+ for (const name of names) {
839
+ try {
840
+ out[name] = fs4.readFileSync(resolveAgentFile(profile.dir, name), "utf-8");
841
+ } catch {
842
+ }
843
+ }
844
+ return out;
845
+ }
846
+ function loadSubagents(profile) {
847
+ const names = profile.claudeCode.subagents;
848
+ if (!names || names.length === 0) return void 0;
849
+ const agents = {};
850
+ for (const name of names) {
851
+ const raw = profile.subagentTemplates?.[name] ?? fs4.readFileSync(resolveAgentFile(profile.dir, name), "utf-8");
852
+ const { fm, body } = splitFrontmatter(raw);
853
+ if (!body) throw new Error(`loadSubagents: agent '${name}' has an empty prompt body`);
854
+ const def = {
855
+ description: fm.description ?? `Subagent ${name}`,
856
+ prompt: body,
857
+ model: "inherit"
858
+ };
859
+ if (fm.tools) {
860
+ const tools = fm.tools.split(",").map((t) => t.trim()).filter(Boolean);
861
+ if (tools.length > 0) def.tools = tools;
862
+ }
863
+ agents[fm.name || name] = def;
864
+ }
865
+ return agents;
866
+ }
867
+ var init_subagents = __esm({
868
+ "src/subagents.ts"() {
869
+ "use strict";
870
+ init_buildSyntheticPlugin();
871
+ }
872
+ });
873
+
692
874
  // src/events.ts
693
875
  var events_exports = {};
694
876
  __export(events_exports, {
@@ -699,8 +881,8 @@ __export(events_exports, {
699
881
  resolveRunId: () => resolveRunId
700
882
  });
701
883
  import * as crypto from "crypto";
702
- import * as fs3 from "fs";
703
- import * as path4 from "path";
884
+ import * as fs5 from "fs";
885
+ import * as path6 from "path";
704
886
  function resolveRunId() {
705
887
  if (process.env.KODY_RUN_ID) {
706
888
  cachedRunId = process.env.KODY_RUN_ID;
@@ -733,16 +915,16 @@ function emitEvent(cwd, ev) {
733
915
  ...ev
734
916
  };
735
917
  const file = eventsPath(cwd, runId);
736
- fs3.mkdirSync(path4.dirname(file), { recursive: true });
737
- fs3.appendFileSync(file, `${JSON.stringify(fullEvent)}
918
+ fs5.mkdirSync(path6.dirname(file), { recursive: true });
919
+ fs5.appendFileSync(file, `${JSON.stringify(fullEvent)}
738
920
  `);
739
921
  } catch {
740
922
  }
741
923
  }
742
924
  function readEvents(cwd, runId) {
743
925
  const file = eventsPath(cwd, runId);
744
- if (!fs3.existsSync(file)) return [];
745
- const lines = fs3.readFileSync(file, "utf-8").split("\n");
926
+ if (!fs5.existsSync(file)) return [];
927
+ const lines = fs5.readFileSync(file, "utf-8").split("\n");
746
928
  const out = [];
747
929
  for (const line of lines) {
748
930
  const trimmed = line.trim();
@@ -756,10 +938,10 @@ function readEvents(cwd, runId) {
756
938
  }
757
939
  function listRuns(cwd) {
758
940
  const runsDir = runtimeStatePath(cwd, "agent-runs");
759
- if (!fs3.existsSync(runsDir)) return [];
760
- return fs3.readdirSync(runsDir).filter((name) => {
941
+ if (!fs5.existsSync(runsDir)) return [];
942
+ return fs5.readdirSync(runsDir).filter((name) => {
761
943
  try {
762
- return fs3.statSync(path4.join(runsDir, name)).isDirectory();
944
+ return fs5.statSync(path6.join(runsDir, name)).isDirectory();
763
945
  } catch {
764
946
  return false;
765
947
  }
@@ -1681,8 +1863,8 @@ var init_issue = __esm({
1681
1863
  });
1682
1864
 
1683
1865
  // src/capabilityFolders.ts
1684
- import * as fs4 from "fs";
1685
- import * as path5 from "path";
1866
+ import * as fs6 from "fs";
1867
+ import * as path7 from "path";
1686
1868
  function capabilityOutputConditionPaths(config) {
1687
1869
  if (config.outputSchema) {
1688
1870
  return new Set(schemaPropertyPaths(config.outputSchema, "result"));
@@ -1697,32 +1879,32 @@ function capabilityOutputConditionPaths(config) {
1697
1879
  ]);
1698
1880
  }
1699
1881
  function listCapabilityFolderSlugs(absDir) {
1700
- if (!fs4.existsSync(absDir)) return [];
1882
+ if (!fs6.existsSync(absDir)) return [];
1701
1883
  let entries;
1702
1884
  try {
1703
- entries = fs4.readdirSync(absDir, { withFileTypes: true });
1885
+ entries = fs6.readdirSync(absDir, { withFileTypes: true });
1704
1886
  } catch {
1705
1887
  return [];
1706
1888
  }
1707
- return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(path5.join(absDir, e.name))).map((e) => e.name).sort();
1889
+ return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(path7.join(absDir, e.name))).map((e) => e.name).sort();
1708
1890
  }
1709
1891
  function isCapabilityFolder(dir) {
1710
- if (!fs4.existsSync(path5.join(dir, CAPABILITY_BODY_FILE))) return false;
1711
- const entries = fs4.readdirSync(dir, { withFileTypes: true });
1892
+ if (!fs6.existsSync(path7.join(dir, CAPABILITY_BODY_FILE))) return false;
1893
+ const entries = fs6.readdirSync(dir, { withFileTypes: true });
1712
1894
  return entries.every(
1713
1895
  (entry) => entry.name === CAPABILITY_BODY_FILE || entry.name === CAPABILITY_CONTRACT_FILE || entry.isDirectory() && (entry.name === "skills" || entry.name === "tools")
1714
1896
  );
1715
1897
  }
1716
1898
  function readCapabilityFolder(root, slug) {
1717
- const dir = path5.join(root, slug);
1718
- const bodyPath = path5.join(dir, CAPABILITY_BODY_FILE);
1719
- const contractPath = path5.join(dir, CAPABILITY_CONTRACT_FILE);
1720
- if (!fs4.existsSync(bodyPath) || !fs4.statSync(bodyPath).isFile()) return null;
1899
+ const dir = path7.join(root, slug);
1900
+ const bodyPath = path7.join(dir, CAPABILITY_BODY_FILE);
1901
+ const contractPath = path7.join(dir, CAPABILITY_CONTRACT_FILE);
1902
+ if (!fs6.existsSync(bodyPath) || !fs6.statSync(bodyPath).isFile()) return null;
1721
1903
  if (!isCapabilityFolder(dir)) return null;
1722
1904
  try {
1723
- const rawBody = fs4.readFileSync(bodyPath, "utf-8");
1724
- const contract = fs4.existsSync(contractPath) ? parseCapabilityContract(fs4.readFileSync(contractPath, "utf-8")) : void 0;
1725
- if (contract?.execution === "script" && !isRegularFile(path5.join(dir, "tools", "run.sh"))) {
1905
+ const rawBody = fs6.readFileSync(bodyPath, "utf-8");
1906
+ const contract = fs6.existsSync(contractPath) ? parseCapabilityContract(fs6.readFileSync(contractPath, "utf-8")) : void 0;
1907
+ if (contract?.execution === "script" && !isRegularFile(path7.join(dir, "tools", "run.sh"))) {
1726
1908
  throw new Error('script-backed Capability requires a regular "tools/run.sh" file');
1727
1909
  }
1728
1910
  const { title, body } = parseCapabilityBody(rawBody, slug);
@@ -1793,7 +1975,7 @@ function parseCapabilityContract(raw) {
1793
1975
  }
1794
1976
  function isRegularFile(filePath) {
1795
1977
  try {
1796
- const stat = fs4.lstatSync(filePath);
1978
+ const stat = fs6.lstatSync(filePath);
1797
1979
  return stat.isFile() && !stat.isSymbolicLink();
1798
1980
  } catch {
1799
1981
  return false;
@@ -1952,51 +2134,51 @@ var init_capabilityFolders = __esm({
1952
2134
  });
1953
2135
 
1954
2136
  // src/definition-paths.ts
1955
- import * as fs5 from "fs";
1956
- import * as path6 from "path";
2137
+ import * as fs7 from "fs";
2138
+ import * as path8 from "path";
1957
2139
  function definitionsRoot(cwd = process.cwd()) {
1958
2140
  const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
1959
2141
  const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
1960
- if (override && overrideCwd && path6.resolve(cwd) === path6.resolve(overrideCwd)) {
1961
- return storeCatalogRoot(path6.resolve(override));
2142
+ if (override && overrideCwd && path8.resolve(cwd) === path8.resolve(overrideCwd)) {
2143
+ return storeCatalogRoot(path8.resolve(override));
1962
2144
  }
1963
- const hydrated = path6.join(cwd, ".kody-engine", "definitions");
1964
- if (fs5.existsSync(hydrated)) return hydrated;
1965
- return override ? storeCatalogRoot(path6.resolve(override)) : hydrated;
2145
+ const hydrated = path8.join(cwd, ".kody-engine", "definitions");
2146
+ if (fs7.existsSync(hydrated)) return hydrated;
2147
+ return override ? storeCatalogRoot(path8.resolve(override)) : hydrated;
1966
2148
  }
1967
2149
  function hasExplicitDefinitionsRoot(cwd = process.cwd(), env = process.env) {
1968
2150
  const root = env.KODY_DEFINITIONS_ROOT?.trim();
1969
2151
  const rootCwd = env.KODY_DEFINITIONS_ROOT_CWD?.trim();
1970
- return Boolean(root && rootCwd && path6.resolve(cwd) === path6.resolve(rootCwd));
2152
+ return Boolean(root && rootCwd && path8.resolve(cwd) === path8.resolve(rootCwd));
1971
2153
  }
1972
2154
  function capabilitiesRoot(cwd = process.cwd()) {
1973
- return storeAssetRoot(cwd, "capabilities") ?? path6.join(definitionsRoot(cwd), "capabilities");
2155
+ return storeAssetRoot(cwd, "capabilities") ?? path8.join(definitionsRoot(cwd), "capabilities");
1974
2156
  }
1975
2157
  function implementationsRoot(cwd = process.cwd()) {
1976
- return path6.join(definitionsRoot(cwd), "implementations");
2158
+ return path8.join(definitionsRoot(cwd), "implementations");
1977
2159
  }
1978
2160
  function agentsRoot(cwd = process.cwd()) {
1979
- return storeAssetRoot(cwd, "agent") ?? path6.join(definitionsRoot(cwd), "agents");
2161
+ return storeAssetRoot(cwd, "agent") ?? path8.join(definitionsRoot(cwd), "agents");
1980
2162
  }
1981
2163
  function storeCatalogRoot(root) {
1982
2164
  const manifest = readStoreManifest(root);
1983
- const roots = ["capabilities", "workflows", "loops"].map((kind) => manifest?.assetRoots?.[kind]).filter((value) => typeof value === "string" && Boolean(value.trim())).map((value) => path6.dirname(value));
1984
- return roots.length === 3 && new Set(roots).size === 1 ? path6.join(root, roots[0]) : root;
2165
+ const roots = ["capabilities", "workflows", "loops"].map((kind) => manifest?.assetRoots?.[kind]).filter((value) => typeof value === "string" && Boolean(value.trim())).map((value) => path8.dirname(value));
2166
+ return roots.length === 3 && new Set(roots).size === 1 ? path8.join(root, roots[0]) : root;
1985
2167
  }
1986
2168
  function storeAssetRoot(cwd, kind) {
1987
2169
  const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
1988
2170
  if (!override) return null;
1989
2171
  const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
1990
- if (overrideCwd && path6.resolve(cwd) !== path6.resolve(overrideCwd)) return null;
1991
- const root = path6.resolve(override);
2172
+ if (overrideCwd && path8.resolve(cwd) !== path8.resolve(overrideCwd)) return null;
2173
+ const root = path8.resolve(override);
1992
2174
  const configured = readStoreManifest(root)?.assetRoots?.[kind];
1993
- return typeof configured === "string" && configured.trim() ? path6.join(root, configured) : null;
2175
+ return typeof configured === "string" && configured.trim() ? path8.join(root, configured) : null;
1994
2176
  }
1995
2177
  function readStoreManifest(root) {
1996
- const file = path6.join(root, "kody-store.json");
1997
- if (!fs5.existsSync(file)) return null;
2178
+ const file = path8.join(root, "kody-store.json");
2179
+ if (!fs7.existsSync(file)) return null;
1998
2180
  try {
1999
- return JSON.parse(fs5.readFileSync(file, "utf8"));
2181
+ return JSON.parse(fs7.readFileSync(file, "utf8"));
2000
2182
  } catch {
2001
2183
  return null;
2002
2184
  }
@@ -2008,32 +2190,32 @@ var init_definition_paths = __esm({
2008
2190
  });
2009
2191
 
2010
2192
  // src/registry.ts
2011
- import * as fs6 from "fs";
2012
- import * as path7 from "path";
2193
+ import * as fs8 from "fs";
2194
+ import * as path9 from "path";
2013
2195
  function getImplementationsRoot() {
2014
- const here = path7.dirname(new URL(import.meta.url).pathname);
2196
+ const here = path9.dirname(new URL(import.meta.url).pathname);
2015
2197
  const candidates = [
2016
- path7.join(here, "implementations"),
2198
+ path9.join(here, "implementations"),
2017
2199
  // dev: src/
2018
- path7.join(here, "..", "implementations"),
2200
+ path9.join(here, "..", "implementations"),
2019
2201
  // built: dist/bin → dist/implementations
2020
- path7.join(here, "..", "src", "implementations")
2202
+ path9.join(here, "..", "src", "implementations")
2021
2203
  // fallback
2022
2204
  ];
2023
2205
  for (const c of candidates) {
2024
- if (fs6.existsSync(c) && fs6.statSync(c).isDirectory()) return c;
2206
+ if (fs8.existsSync(c) && fs8.statSync(c).isDirectory()) return c;
2025
2207
  }
2026
2208
  return candidates[0];
2027
2209
  }
2028
2210
  function getRuntimeServicesRoot() {
2029
- const here = path7.dirname(new URL(import.meta.url).pathname);
2211
+ const here = path9.dirname(new URL(import.meta.url).pathname);
2030
2212
  const candidates = [
2031
- path7.join(here, "runtime-services"),
2032
- path7.join(here, "..", "runtime-services"),
2033
- path7.join(here, "..", "src", "runtime-services")
2213
+ path9.join(here, "runtime-services"),
2214
+ path9.join(here, "..", "runtime-services"),
2215
+ path9.join(here, "..", "src", "runtime-services")
2034
2216
  ];
2035
2217
  for (const candidate of candidates) {
2036
- if (fs6.existsSync(candidate) && fs6.statSync(candidate).isDirectory()) return candidate;
2218
+ if (fs8.existsSync(candidate) && fs8.statSync(candidate).isDirectory()) return candidate;
2037
2219
  }
2038
2220
  return candidates[0];
2039
2221
  }
@@ -2041,17 +2223,17 @@ function getProjectCapabilitiesRoot() {
2041
2223
  return capabilitiesRoot();
2042
2224
  }
2043
2225
  function getBuiltinCapabilitiesRoot() {
2044
- const here = path7.dirname(new URL(import.meta.url).pathname);
2226
+ const here = path9.dirname(new URL(import.meta.url).pathname);
2045
2227
  const candidates = [
2046
- path7.join(here, "capabilities"),
2228
+ path9.join(here, "capabilities"),
2047
2229
  // dev: src/
2048
- path7.join(here, "..", "capabilities"),
2230
+ path9.join(here, "..", "capabilities"),
2049
2231
  // built: dist/bin → dist/capabilities
2050
- path7.join(here, "..", "src", "capabilities")
2232
+ path9.join(here, "..", "src", "capabilities")
2051
2233
  // fallback
2052
2234
  ];
2053
2235
  for (const c of candidates) {
2054
- if (fs6.existsSync(c) && fs6.statSync(c).isDirectory()) return c;
2236
+ if (fs8.existsSync(c) && fs8.statSync(c).isDirectory()) return c;
2055
2237
  }
2056
2238
  return candidates[0];
2057
2239
  }
@@ -2074,14 +2256,14 @@ function listImplementations(roots = getImplementationRoots()) {
2074
2256
  const seen = /* @__PURE__ */ new Set();
2075
2257
  const out = [];
2076
2258
  for (const root of rootList) {
2077
- if (!fs6.existsSync(root)) continue;
2259
+ if (!fs8.existsSync(root)) continue;
2078
2260
  const requireImplementationProfile = isCapabilityRoot(root);
2079
- const entries = fs6.readdirSync(root, { withFileTypes: true });
2261
+ const entries = fs8.readdirSync(root, { withFileTypes: true });
2080
2262
  for (const ent of entries) {
2081
2263
  if (!ent.isDirectory()) continue;
2082
2264
  if (seen.has(ent.name)) continue;
2083
2265
  const profilePath = implementationRuntimePath(root, ent.name);
2084
- if (fs6.existsSync(profilePath) && fs6.statSync(profilePath).isFile() && isImplementationProfile(profilePath, requireImplementationProfile)) {
2266
+ if (fs8.existsSync(profilePath) && fs8.statSync(profilePath).isFile() && isImplementationProfile(profilePath, requireImplementationProfile)) {
2085
2267
  out.push({ name: ent.name, profilePath });
2086
2268
  seen.add(ent.name);
2087
2269
  }
@@ -2101,7 +2283,7 @@ function resolveImplementationCandidates(name, roots = getRuntimeProfileRootsFor
2101
2283
  const out = [];
2102
2284
  for (const root of rootList) {
2103
2285
  const profilePath = implementationRuntimePath(root, name);
2104
- if (fs6.existsSync(profilePath) && fs6.statSync(profilePath).isFile() && isImplementationProfile(profilePath, isCapabilityRoot(root))) {
2286
+ if (fs8.existsSync(profilePath) && fs8.statSync(profilePath).isFile() && isImplementationProfile(profilePath, isCapabilityRoot(root))) {
2105
2287
  out.push(profilePath);
2106
2288
  }
2107
2289
  }
@@ -2170,7 +2352,7 @@ function implementationDeclaresInput(implementation, inputName, cwd = process.cw
2170
2352
  const profilePath = resolveImplementation(implementation, getRuntimeProfileRootsForCwd(cwd));
2171
2353
  if (!profilePath) return false;
2172
2354
  try {
2173
- const document = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
2355
+ const document = JSON.parse(fs8.readFileSync(profilePath, "utf-8"));
2174
2356
  const raw = document.config ?? document;
2175
2357
  if (!Array.isArray(raw.inputs)) return false;
2176
2358
  return raw.inputs.some((entry) => {
@@ -2186,29 +2368,29 @@ function isSafeName(name) {
2186
2368
  return /^[a-z][a-z0-9-]*$/.test(name) && !name.includes("..");
2187
2369
  }
2188
2370
  function isCapabilityRoot(root) {
2189
- const normalized = path7.normalize(root);
2190
- if (path7.basename(normalized) === "capabilities") return true;
2371
+ const normalized = path9.normalize(root);
2372
+ if (path9.basename(normalized) === "capabilities") return true;
2191
2373
  const knownRoots = [getProjectCapabilitiesRoot(), getBuiltinCapabilitiesRoot()];
2192
- return knownRoots.some((candidate) => candidate && path7.normalize(candidate) === normalized);
2374
+ return knownRoots.some((candidate) => candidate && path9.normalize(candidate) === normalized);
2193
2375
  }
2194
2376
  function implementationRuntimePath(root, name) {
2195
- const runtimePath = path7.join(root, name, "runtime.json");
2196
- if (fs6.existsSync(runtimePath)) return runtimePath;
2197
- const internalProfilePath = path7.join(root, name, "profile.json");
2198
- if (fs6.existsSync(internalProfilePath)) return internalProfilePath;
2199
- return path7.join(root, name, CAPABILITY_PROFILE_FILE);
2377
+ const runtimePath = path9.join(root, name, "runtime.json");
2378
+ if (fs8.existsSync(runtimePath)) return runtimePath;
2379
+ const internalProfilePath = path9.join(root, name, "profile.json");
2380
+ if (fs8.existsSync(internalProfilePath)) return internalProfilePath;
2381
+ return path9.join(root, name, CAPABILITY_PROFILE_FILE);
2200
2382
  }
2201
2383
  function isImplementationProfile(profilePath, requireImplementationProfile) {
2202
2384
  if (!requireImplementationProfile) return true;
2203
2385
  try {
2204
- const raw = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
2386
+ const raw = JSON.parse(fs8.readFileSync(profilePath, "utf-8"));
2205
2387
  return typeof raw.role === "string" && PUBLIC_IMPLEMENTATION_ROLES.has(raw.role);
2206
2388
  } catch {
2207
2389
  return false;
2208
2390
  }
2209
2391
  }
2210
2392
  function listFolderCapabilityActions(root, source) {
2211
- if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
2393
+ if (!fs8.existsSync(root) || !fs8.statSync(root).isDirectory()) return [];
2212
2394
  const out = [];
2213
2395
  for (const slug of listCapabilityFolderSlugs(root)) {
2214
2396
  if (!isSafeName(slug)) continue;
@@ -2240,7 +2422,7 @@ function hasUnresolvedExplicitImplementation(capability, implementation) {
2240
2422
  return resolveImplementation(implementation) === null;
2241
2423
  }
2242
2424
  function listBuiltinCapabilityActions(root = getBuiltinCapabilitiesRoot()) {
2243
- if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
2425
+ if (!fs8.existsSync(root) || !fs8.statSync(root).isDirectory()) return [];
2244
2426
  const out = [];
2245
2427
  for (const slug of listCapabilityFolderSlugs(root)) {
2246
2428
  if (!isSafeName(slug)) continue;
@@ -2265,7 +2447,7 @@ function getProfileInputs(name, roots = getImplementationRoots()) {
2265
2447
  const profilePath = resolveImplementation(name, roots);
2266
2448
  if (!profilePath) return null;
2267
2449
  try {
2268
- const document = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
2450
+ const document = JSON.parse(fs8.readFileSync(profilePath, "utf-8"));
2269
2451
  if (!document || typeof document !== "object") return [];
2270
2452
  const raw = "config" in document && document.config && typeof document.config === "object" ? document.config : document;
2271
2453
  if (!Array.isArray(raw.inputs)) return [];
@@ -3303,8 +3485,8 @@ var init_capabilityMcp = __esm({
3303
3485
 
3304
3486
  // src/repoWorkspace.ts
3305
3487
  import { spawn as spawn2, spawnSync } from "child_process";
3306
- import * as fs7 from "fs";
3307
- import * as path8 from "path";
3488
+ import * as fs9 from "fs";
3489
+ import * as path10 from "path";
3308
3490
  function buildCloneProcess(repo, token, baseEnv = process.env) {
3309
3491
  const url = `https://github.com/${repo}.git`;
3310
3492
  const env = { ...baseEnv };
@@ -3319,10 +3501,10 @@ function buildCloneProcess(repo, token, baseEnv = process.env) {
3319
3501
  async function resolveAndClone(reposRoot, repo, repoToken, cloneRepo) {
3320
3502
  const name = repo?.trim();
3321
3503
  if (!name || !REPO_RE.test(name)) return null;
3322
- const root = path8.resolve(reposRoot);
3323
- const dir = path8.resolve(root, name);
3324
- if (dir !== root && !dir.startsWith(root + path8.sep)) return null;
3325
- if (fs7.existsSync(path8.join(dir, ".git"))) return dir;
3504
+ const root = path10.resolve(reposRoot);
3505
+ const dir = path10.resolve(root, name);
3506
+ if (dir !== root && !dir.startsWith(root + path10.sep)) return null;
3507
+ if (fs9.existsSync(path10.join(dir, ".git"))) return dir;
3326
3508
  const inflight = repoClones.get(dir);
3327
3509
  if (inflight) {
3328
3510
  await inflight;
@@ -3354,7 +3536,7 @@ var init_repoWorkspace = __esm({
3354
3536
  repoClones = /* @__PURE__ */ new Map();
3355
3537
  GIT_CREDENTIAL_HELPER = `!f() { if [ "$1" = get ] && [ -n "$GITHUB_TOKEN" ]; then printf '%s\\n' username=x-access-token "password=$GITHUB_TOKEN"; fi; }; f`;
3356
3538
  defaultCloneRepo = (repo, token, dir) => {
3357
- fs7.mkdirSync(path8.dirname(dir), { recursive: true });
3539
+ fs9.mkdirSync(path10.dirname(dir), { recursive: true });
3358
3540
  const clone = buildCloneProcess(repo, token);
3359
3541
  return new Promise((resolve19, reject) => {
3360
3542
  const child = spawn2("git", ["clone", "--depth=1", clone.url, dir], {
@@ -3448,8 +3630,8 @@ var init_fetchRepoMcp = __esm({
3448
3630
  });
3449
3631
 
3450
3632
  // src/agent.ts
3451
- import * as fs8 from "fs";
3452
- import * as path9 from "path";
3633
+ import * as fs10 from "fs";
3634
+ import * as path11 from "path";
3453
3635
  import { query } from "@anthropic-ai/claude-agent-sdk";
3454
3636
  function classifySubtype(subtype) {
3455
3637
  if (!subtype) return "generic_failed";
@@ -3518,8 +3700,8 @@ function buildAgentEnvironment(baseEnv, repoToken, requestEnvironment) {
3518
3700
  }
3519
3701
  async function runAgent(opts) {
3520
3702
  const ndjsonDir = opts.ndjsonDir ?? agentRunDir(opts.cwd);
3521
- fs8.mkdirSync(ndjsonDir, { recursive: true });
3522
- const ndjsonPath = path9.join(ndjsonDir, "last-run.jsonl");
3703
+ fs10.mkdirSync(ndjsonDir, { recursive: true });
3704
+ const ndjsonPath = path11.join(ndjsonDir, "last-run.jsonl");
3523
3705
  const env = buildAgentEnvironment(process.env, opts.repoToken, opts.environment);
3524
3706
  if (opts.litellmUrl) {
3525
3707
  env.ANTHROPIC_BASE_URL = opts.litellmUrl;
@@ -3538,7 +3720,7 @@ async function runAgent(opts) {
3538
3720
  for (let attempt = 0; ; attempt++) {
3539
3721
  let ndjsonWriteFailed = false;
3540
3722
  let ndjsonWriteError;
3541
- const fullLog = fs8.createWriteStream(ndjsonPath, { flags: "w" });
3723
+ const fullLog = fs10.createWriteStream(ndjsonPath, { flags: "w" });
3542
3724
  fullLog.on("error", (err) => {
3543
3725
  ndjsonWriteFailed = true;
3544
3726
  ndjsonWriteError = err instanceof Error ? err.message : String(err);
@@ -3562,7 +3744,15 @@ async function runAgent(opts) {
3562
3744
  // opt-in tools like fetch_repo can be appended below.
3563
3745
  allowedTools: [...opts.allowedToolsOverride ?? DEFAULT_ALLOWED_TOOLS],
3564
3746
  permissionMode: opts.permissionModeOverride ?? "acceptEdits",
3565
- env
3747
+ env,
3748
+ hooks: {
3749
+ PreToolUse: [
3750
+ {
3751
+ matcher: "Agent",
3752
+ hooks: [enforceSubagentModelInheritance]
3753
+ }
3754
+ ]
3755
+ }
3566
3756
  };
3567
3757
  const additionalDirectories = new Set(opts.additionalDirectories ?? []);
3568
3758
  const mcpEntries = [];
@@ -3893,6 +4083,7 @@ var init_agent = __esm({
3893
4083
  init_config();
3894
4084
  init_format();
3895
4085
  init_runtimePaths();
4086
+ init_subagents();
3896
4087
  DEFAULT_ALLOWED_TOOLS = ["Bash", "Edit", "Read", "Write", "Glob", "Grep"];
3897
4088
  DEFAULT_TURN_TIMEOUT_MS = 6e5;
3898
4089
  MAX_CONNECTION_RETRIES = 2;
@@ -3911,8 +4102,8 @@ var init_agent = __esm({
3911
4102
  });
3912
4103
 
3913
4104
  // src/agents.ts
3914
- import * as fs9 from "fs";
3915
- import * as path10 from "path";
4105
+ import * as fs11 from "fs";
4106
+ import * as path12 from "path";
3916
4107
  function stripFrontmatter(raw) {
3917
4108
  const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
3918
4109
  return (match ? match[1] : raw).trim();
@@ -3920,9 +4111,9 @@ function stripFrontmatter(raw) {
3920
4111
  function loadAgentIdentity(cwd, slug, agentsDir = agentsRoot(cwd)) {
3921
4112
  const trimmed = slug.trim();
3922
4113
  if (!trimmed) throw new Error("loadAgentIdentity: empty agent slug");
3923
- const agentPath = resolveAgentFile(cwd, trimmed, agentsDir);
3924
- if (fs9.existsSync(agentPath)) {
3925
- const body = stripFrontmatter(fs9.readFileSync(agentPath, "utf-8"));
4114
+ const agentPath = resolveAgentFile2(cwd, trimmed, agentsDir);
4115
+ if (fs11.existsSync(agentPath)) {
4116
+ const body = stripFrontmatter(fs11.readFileSync(agentPath, "utf-8"));
3926
4117
  if (body) return body;
3927
4118
  const builtinForEmpty = BUILTIN_AGENTS[trimmed];
3928
4119
  if (builtinForEmpty) return builtinForEmpty;
@@ -3932,9 +4123,9 @@ function loadAgentIdentity(cwd, slug, agentsDir = agentsRoot(cwd)) {
3932
4123
  if (builtin) return builtin;
3933
4124
  throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
3934
4125
  }
3935
- function resolveAgentFile(cwd, slug, agentsDir = agentsRoot(cwd)) {
3936
- const localPath = path10.resolve(cwd, agentsDir, `${slug}.md`);
3937
- if (fs9.existsSync(localPath)) return localPath;
4126
+ function resolveAgentFile2(cwd, slug, agentsDir = agentsRoot(cwd)) {
4127
+ const localPath = path12.resolve(cwd, agentsDir, `${slug}.md`);
4128
+ if (fs11.existsSync(localPath)) return localPath;
3938
4129
  return localPath;
3939
4130
  }
3940
4131
  function frameAgentIdentity(slug, agent) {
@@ -3966,14 +4157,14 @@ var init_agents = __esm({
3966
4157
  });
3967
4158
 
3968
4159
  // src/task-artifacts.ts
3969
- import fs10 from "fs";
3970
- import path11 from "path";
4160
+ import fs12 from "fs";
4161
+ import path13 from "path";
3971
4162
  import posixPath from "path/posix";
3972
4163
  function prepareTaskArtifactsDir(cwd, taskId) {
3973
4164
  const safeId = String(taskId).replace(/[^a-zA-Z0-9._-]/g, "_");
3974
4165
  const absDir = runtimeStatePath(cwd, "task-artifacts", safeId);
3975
4166
  const relDir = absDir;
3976
- fs10.mkdirSync(absDir, { recursive: true });
4167
+ fs12.mkdirSync(absDir, { recursive: true });
3977
4168
  return { taskId: safeId, absDir, relDir };
3978
4169
  }
3979
4170
  function initializeTaskArtifacts(artifacts, metadata = { taskType: "job" }) {
@@ -4003,16 +4194,16 @@ function initializeTaskArtifacts(artifacts, metadata = { taskType: "job" }) {
4003
4194
  "handoff-notes.md": "Baseline handoff: the agent did not provide additional notes.\n"
4004
4195
  };
4005
4196
  for (const file of TASK_ARTIFACT_FILES) {
4006
- const full = path11.join(artifacts.absDir, file);
4007
- if (!fs10.existsSync(full)) fs10.writeFileSync(full, defaults[file], "utf8");
4197
+ const full = path13.join(artifacts.absDir, file);
4198
+ if (!fs12.existsSync(full)) fs12.writeFileSync(full, defaults[file], "utf8");
4008
4199
  }
4009
4200
  }
4010
4201
  function verifyTaskArtifacts(absDir) {
4011
4202
  const missing = [];
4012
4203
  for (const name of TASK_ARTIFACT_FILES) {
4013
- const full = path11.join(absDir, name);
4204
+ const full = path13.join(absDir, name);
4014
4205
  try {
4015
- const stat = fs10.statSync(full);
4206
+ const stat = fs12.statSync(full);
4016
4207
  if (!stat.isFile() || stat.size === 0) missing.push(name);
4017
4208
  } catch {
4018
4209
  missing.push(name);
@@ -4028,11 +4219,11 @@ async function persistTaskArtifactsToState(config, _cwd, artifacts) {
4028
4219
  if (hasStateBackendConfig() && tenantId2) {
4029
4220
  const backend = createStateBackendFromEnv();
4030
4221
  for (const file of TASK_ARTIFACT_FILES) {
4031
- const full = path11.join(artifacts.absDir, file);
4032
- if (!fs10.existsSync(full)) continue;
4033
- const stat = fs10.statSync(full);
4222
+ const full = path13.join(artifacts.absDir, file);
4223
+ if (!fs12.existsSync(full)) continue;
4224
+ const stat = fs12.statSync(full);
4034
4225
  if (!stat.isFile() || stat.size === 0) continue;
4035
- const content = fs10.readFileSync(full, "utf-8");
4226
+ const content = fs12.readFileSync(full, "utf-8");
4036
4227
  const kind = file.replace(/\.(json|md)$/, "");
4037
4228
  let doc = content;
4038
4229
  if (file.endsWith(".json")) {
@@ -4393,8 +4584,8 @@ var init_workflowValidation = __esm({
4393
4584
  });
4394
4585
 
4395
4586
  // src/workflowDefinitions.ts
4396
- import * as fs16 from "fs";
4397
- import * as path17 from "path";
4587
+ import * as fs18 from "fs";
4588
+ import * as path19 from "path";
4398
4589
  function isWorkflowDefinitionId(value) {
4399
4590
  return WORKFLOW_ID_PATTERN.test(value);
4400
4591
  }
@@ -4437,12 +4628,12 @@ function readWorkflowDefinition(_config, cwd, id) {
4437
4628
  const root = cwd ?? process.cwd();
4438
4629
  const relativePath = workflowDefinitionPath(id);
4439
4630
  const candidates = [
4440
- path17.join(root, ".kody-engine", "runtime", relativePath),
4441
- path17.join(definitionsRoot(root), relativePath)
4631
+ path19.join(root, ".kody-engine", "runtime", relativePath),
4632
+ path19.join(definitionsRoot(root), relativePath)
4442
4633
  ];
4443
4634
  for (const filePath of candidates) {
4444
- if (!fs16.existsSync(filePath)) continue;
4445
- const workflow = parseWorkflowDefinition(fs16.readFileSync(filePath, "utf8"));
4635
+ if (!fs18.existsSync(filePath)) continue;
4636
+ const workflow = parseWorkflowDefinition(fs18.readFileSync(filePath, "utf8"));
4446
4637
  if (workflow) return workflow;
4447
4638
  }
4448
4639
  return null;
@@ -4450,7 +4641,7 @@ function readWorkflowDefinition(_config, cwd, id) {
4450
4641
  function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
4451
4642
  return {
4452
4643
  slug: id,
4453
- dir: path17.dirname(source),
4644
+ dir: path19.dirname(source),
4454
4645
  profilePath: source,
4455
4646
  bodyPath: source,
4456
4647
  title: workflow.name,
@@ -4505,7 +4696,7 @@ var init_workflowDefinitions = __esm({
4505
4696
 
4506
4697
  // src/gha.ts
4507
4698
  import { execFileSync as execFileSync2 } from "child_process";
4508
- import * as fs19 from "fs";
4699
+ import * as fs21 from "fs";
4509
4700
  function getRunUrl() {
4510
4701
  const server = process.env.GITHUB_SERVER_URL;
4511
4702
  const repo = process.env.GITHUB_REPOSITORY;
@@ -4516,10 +4707,10 @@ function getRunUrl() {
4516
4707
  function reactToTriggerComment(cwd) {
4517
4708
  if (process.env.GITHUB_EVENT_NAME !== "issue_comment") return;
4518
4709
  const eventPath = process.env.GITHUB_EVENT_PATH;
4519
- if (!eventPath || !fs19.existsSync(eventPath)) return;
4710
+ if (!eventPath || !fs21.existsSync(eventPath)) return;
4520
4711
  let event = null;
4521
4712
  try {
4522
- event = JSON.parse(fs19.readFileSync(eventPath, "utf-8"));
4713
+ event = JSON.parse(fs21.readFileSync(eventPath, "utf-8"));
4523
4714
  } catch {
4524
4715
  return;
4525
4716
  }
@@ -5100,166 +5291,6 @@ var init_lifecycles = __esm({
5100
5291
  }
5101
5292
  });
5102
5293
 
5103
- // src/scripts/buildSyntheticPlugin.ts
5104
- import * as fs20 from "fs";
5105
- import * as os3 from "os";
5106
- import * as path19 from "path";
5107
- function getPluginsCatalogRoot() {
5108
- const here = path19.dirname(new URL(import.meta.url).pathname);
5109
- const candidates = [
5110
- path19.join(here, "..", "plugins"),
5111
- // dev: src/scripts → src/plugins
5112
- path19.join(here, "..", "..", "plugins"),
5113
- // built: dist/scripts → dist/plugins
5114
- path19.join(here, "..", "..", "src", "plugins")
5115
- // fallback
5116
- ];
5117
- for (const c of candidates) {
5118
- if (fs20.existsSync(c) && fs20.statSync(c).isDirectory()) return c;
5119
- }
5120
- return candidates[0];
5121
- }
5122
- function copyDir(src, dst) {
5123
- fs20.mkdirSync(dst, { recursive: true });
5124
- for (const ent of fs20.readdirSync(src, { withFileTypes: true })) {
5125
- const s = path19.join(src, ent.name);
5126
- const d = path19.join(dst, ent.name);
5127
- if (ent.isDirectory()) copyDir(s, d);
5128
- else if (ent.isFile()) fs20.copyFileSync(s, d);
5129
- }
5130
- }
5131
- var buildSyntheticPlugin;
5132
- var init_buildSyntheticPlugin = __esm({
5133
- "src/scripts/buildSyntheticPlugin.ts"() {
5134
- "use strict";
5135
- buildSyntheticPlugin = async (ctx, profile) => {
5136
- const cc = profile.claudeCode;
5137
- const needsSynthetic = cc.skills.length > 0 || cc.commands.length > 0 || cc.hooks.length > 0;
5138
- if (!needsSynthetic) return;
5139
- const catalog = getPluginsCatalogRoot();
5140
- const runId = `${profile.name}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
5141
- const root = path19.join(os3.tmpdir(), `kody-synth-${runId}`);
5142
- fs20.mkdirSync(path19.join(root, ".claude-plugin"), { recursive: true });
5143
- const resolvePart = (bucket, entry) => {
5144
- const local = path19.join(profile.dir, bucket, entry);
5145
- if (fs20.existsSync(local)) return local;
5146
- const shared = path19.resolve(profile.dir, "..", "..", "shared", bucket, entry);
5147
- if (fs20.existsSync(shared)) return shared;
5148
- const central = path19.join(catalog, bucket, entry);
5149
- if (fs20.existsSync(central)) return central;
5150
- throw new Error(
5151
- `buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${path19.dirname(shared)}/), or catalog (${catalog}/${bucket}/)`
5152
- );
5153
- };
5154
- if (cc.skills.length > 0) {
5155
- const dst = path19.join(root, "skills");
5156
- fs20.mkdirSync(dst, { recursive: true });
5157
- for (const name of cc.skills) {
5158
- copyDir(resolvePart("skills", name), path19.join(dst, name));
5159
- }
5160
- }
5161
- if (cc.commands.length > 0) {
5162
- const dst = path19.join(root, "commands");
5163
- fs20.mkdirSync(dst, { recursive: true });
5164
- for (const name of cc.commands) {
5165
- fs20.copyFileSync(resolvePart("commands", `${name}.md`), path19.join(dst, `${name}.md`));
5166
- }
5167
- }
5168
- if (cc.hooks.length > 0) {
5169
- const dst = path19.join(root, "hooks");
5170
- fs20.mkdirSync(dst, { recursive: true });
5171
- const merged = { hooks: {} };
5172
- for (const name of cc.hooks) {
5173
- const src = resolvePart("hooks", `${name}.json`);
5174
- const parsed = JSON.parse(fs20.readFileSync(src, "utf-8"));
5175
- for (const [event, entries] of Object.entries(parsed.hooks ?? {})) {
5176
- if (!Array.isArray(entries)) continue;
5177
- if (!merged.hooks[event]) merged.hooks[event] = [];
5178
- merged.hooks[event].push(...entries);
5179
- }
5180
- }
5181
- fs20.writeFileSync(path19.join(dst, "hooks.json"), `${JSON.stringify(merged, null, 2)}
5182
- `);
5183
- }
5184
- const manifest = {
5185
- name: `kody-synth-${profile.name}`,
5186
- version: "1.0.0",
5187
- description: `Synthetic plugin assembled by Kody for profile '${profile.name}' at runtime.`
5188
- };
5189
- if (cc.skills.length > 0) manifest.skills = ["./skills/"];
5190
- if (cc.commands.length > 0) manifest.commands = ["./commands/"];
5191
- fs20.writeFileSync(path19.join(root, ".claude-plugin", "plugin.json"), `${JSON.stringify(manifest, null, 2)}
5192
- `);
5193
- ctx.data.syntheticPluginPath = root;
5194
- };
5195
- }
5196
- });
5197
-
5198
- // src/subagents.ts
5199
- import * as fs21 from "fs";
5200
- import * as path20 from "path";
5201
- function splitFrontmatter(raw) {
5202
- const match = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(raw);
5203
- if (!match) return { fm: {}, body: raw.trim() };
5204
- const fm = {};
5205
- for (const line of match[1].split("\n")) {
5206
- const idx = line.indexOf(":");
5207
- if (idx === -1) continue;
5208
- fm[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
5209
- }
5210
- return { fm, body: (match[2] ?? "").trim() };
5211
- }
5212
- function resolveAgentFile2(profileDir, name) {
5213
- const local = path20.join(profileDir, "agents", `${name}.md`);
5214
- if (fs21.existsSync(local)) return local;
5215
- const shared = path20.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
5216
- if (fs21.existsSync(shared)) return shared;
5217
- const central = path20.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
5218
- if (fs21.existsSync(central)) return central;
5219
- throw new Error(
5220
- `loadSubagents: agent '${name}' not found in ${profileDir}/agents/, hydrated shared assets, or engine catalog`
5221
- );
5222
- }
5223
- function captureSubagentTemplates(profile) {
5224
- const names = profile.claudeCode.subagents;
5225
- if (!names || names.length === 0) return {};
5226
- const out = {};
5227
- for (const name of names) {
5228
- try {
5229
- out[name] = fs21.readFileSync(resolveAgentFile2(profile.dir, name), "utf-8");
5230
- } catch {
5231
- }
5232
- }
5233
- return out;
5234
- }
5235
- function loadSubagents(profile) {
5236
- const names = profile.claudeCode.subagents;
5237
- if (!names || names.length === 0) return void 0;
5238
- const agents = {};
5239
- for (const name of names) {
5240
- const raw = profile.subagentTemplates?.[name] ?? fs21.readFileSync(resolveAgentFile2(profile.dir, name), "utf-8");
5241
- const { fm, body } = splitFrontmatter(raw);
5242
- if (!body) throw new Error(`loadSubagents: agent '${name}' has an empty prompt body`);
5243
- const def = {
5244
- description: fm.description ?? `Subagent ${name}`,
5245
- prompt: body
5246
- };
5247
- if (fm.tools) {
5248
- const tools = fm.tools.split(",").map((t) => t.trim()).filter(Boolean);
5249
- if (tools.length > 0) def.tools = tools;
5250
- }
5251
- if (fm.model) def.model = fm.model;
5252
- agents[fm.name || name] = def;
5253
- }
5254
- return agents;
5255
- }
5256
- var init_subagents = __esm({
5257
- "src/subagents.ts"() {
5258
- "use strict";
5259
- init_buildSyntheticPlugin();
5260
- }
5261
- });
5262
-
5263
5294
  // src/profile.ts
5264
5295
  import { createHash as createHash3 } from "crypto";
5265
5296
  import * as fs22 from "fs";
@@ -15005,7 +15036,7 @@ var init_loadAgentAdhoc = __esm({
15005
15036
  if (!agentSlug) {
15006
15037
  throw new Error("loadAgentAdhoc: ctx.args.agent must be a non-empty slug");
15007
15038
  }
15008
- const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
15039
+ const agentPath = resolveAgentFile2(ctx.cwd, agentSlug, agentsDir);
15009
15040
  if (!fs39.existsSync(agentPath)) {
15010
15041
  throw new Error(`loadAgentAdhoc: agent identity not found: ${agentPath}`);
15011
15042
  }
@@ -15430,7 +15461,7 @@ var init_loadJobFromFile = __esm({
15430
15461
  let agentTitle = "";
15431
15462
  let agentIdentity = "";
15432
15463
  if (agentSlug) {
15433
- const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
15464
+ const agentPath = resolveAgentFile2(ctx.cwd, agentSlug, agentsDir);
15434
15465
  if (!fs40.existsSync(agentPath)) {
15435
15466
  throw new Error(
15436
15467
  `loadJobFromFile: capability '${slug}' declares agent '${agentSlug}' but ${agentPath} does not exist`
@@ -22982,13 +23013,13 @@ init_agents();
22982
23013
  init_config();
22983
23014
  init_registry();
22984
23015
  init_task_artifacts();
22985
- import * as fs14 from "fs";
22986
- import * as path15 from "path";
23016
+ import * as fs16 from "fs";
23017
+ import * as path17 from "path";
22987
23018
 
22988
23019
  // src/chat/attachments.ts
22989
23020
  init_runtimePaths();
22990
- import * as fs11 from "fs";
22991
- import * as path12 from "path";
23021
+ import * as fs13 from "fs";
23022
+ import * as path14 from "path";
22992
23023
  var INLINE_ATTACHMENT_RE = /(?:\[(?:Image|File): ([^\]]*)\]\n)?data:([\w.+-]+\/[\w.+-]+);base64,([A-Za-z0-9+/=]+)/g;
22993
23024
  var EXT_BY_MIME = {
22994
23025
  "image/png": "png",
@@ -23021,11 +23052,11 @@ function prepareAttachments(turns, cwd, sessionId) {
23021
23052
  if (!isImage) return `[File: ${name}]`;
23022
23053
  try {
23023
23054
  if (!dirEnsured) {
23024
- fs11.mkdirSync(dir, { recursive: true });
23055
+ fs13.mkdirSync(dir, { recursive: true });
23025
23056
  dirEnsured = true;
23026
23057
  }
23027
- const filePath = path12.join(dir, `${imageCounter}.${extFor(mime)}`);
23028
- fs11.writeFileSync(filePath, Buffer.from(data, "base64"));
23058
+ const filePath = path14.join(dir, `${imageCounter}.${extFor(mime)}`);
23059
+ fs13.writeFileSync(filePath, Buffer.from(data, "base64"));
23029
23060
  imageCounter += 1;
23030
23061
  imagePaths.push(filePath);
23031
23062
  return `[Image "${name}" is attached \u2014 saved to ${filePath}. Use the Read tool on that exact path to view it.]`;
@@ -23042,8 +23073,8 @@ function prepareAttachments(turns, cwd, sessionId) {
23042
23073
 
23043
23074
  // src/chat/codex-app-server.ts
23044
23075
  import { spawn as spawn3 } from "child_process";
23045
- import * as fs12 from "fs";
23046
- import * as path13 from "path";
23076
+ import * as fs14 from "fs";
23077
+ import * as path15 from "path";
23047
23078
  import { createInterface } from "readline";
23048
23079
  function codexThreadStartParams(args) {
23049
23080
  return {
@@ -23214,11 +23245,11 @@ var CodexAppServerClient = class {
23214
23245
  };
23215
23246
  var clients = /* @__PURE__ */ new Map();
23216
23247
  function threadMapPath(cwd) {
23217
- return path13.join(cwd, ".kody-engine", "runtime", "codex-threads.json");
23248
+ return path15.join(cwd, ".kody-engine", "runtime", "codex-threads.json");
23218
23249
  }
23219
23250
  function readThreadMap(cwd) {
23220
23251
  try {
23221
- const value = JSON.parse(fs12.readFileSync(threadMapPath(cwd), "utf8"));
23252
+ const value = JSON.parse(fs14.readFileSync(threadMapPath(cwd), "utf8"));
23222
23253
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
23223
23254
  return Object.fromEntries(
23224
23255
  Object.entries(value).filter(
@@ -23231,8 +23262,8 @@ function readThreadMap(cwd) {
23231
23262
  }
23232
23263
  function writeThreadMap(cwd, map) {
23233
23264
  const file = threadMapPath(cwd);
23234
- fs12.mkdirSync(path13.dirname(file), { recursive: true });
23235
- fs12.writeFileSync(file, `${JSON.stringify(map, null, 2)}
23265
+ fs14.mkdirSync(path15.dirname(file), { recursive: true });
23266
+ fs14.writeFileSync(file, `${JSON.stringify(map, null, 2)}
23236
23267
  `);
23237
23268
  }
23238
23269
  async function runCodexChatTurn(args) {
@@ -23322,8 +23353,8 @@ async function runCodexChatTurn(args) {
23322
23353
  }
23323
23354
 
23324
23355
  // src/chat/events.ts
23325
- import * as fs13 from "fs";
23326
- import * as path14 from "path";
23356
+ import * as fs15 from "fs";
23357
+ import * as path16 from "path";
23327
23358
  import posixPath2 from "path/posix";
23328
23359
  var BackendEventSink = class {
23329
23360
  constructor(append, tenantId2, sessionId) {
@@ -23339,7 +23370,7 @@ var BackendEventSink = class {
23339
23370
  }
23340
23371
  };
23341
23372
  function eventsFilePath(cwd, sessionId) {
23342
- return path14.join(cwd, ".kody-engine", "runtime", "events", `${sessionId}.jsonl`);
23373
+ return path16.join(cwd, ".kody-engine", "runtime", "events", `${sessionId}.jsonl`);
23343
23374
  }
23344
23375
  var FileSink = class {
23345
23376
  constructor(file) {
@@ -23347,8 +23378,8 @@ var FileSink = class {
23347
23378
  }
23348
23379
  file;
23349
23380
  async emit(event) {
23350
- fs13.mkdirSync(path14.dirname(this.file), { recursive: true });
23351
- fs13.appendFileSync(this.file, `${JSON.stringify(event)}
23381
+ fs15.mkdirSync(path16.dirname(this.file), { recursive: true });
23382
+ fs15.appendFileSync(this.file, `${JSON.stringify(event)}
23352
23383
  `);
23353
23384
  }
23354
23385
  };
@@ -23591,7 +23622,7 @@ function buildImplementationCatalog() {
23591
23622
  const entries = [];
23592
23623
  for (const { name, profilePath } of discovered) {
23593
23624
  try {
23594
- const raw = JSON.parse(fs14.readFileSync(profilePath, "utf-8"));
23625
+ const raw = JSON.parse(fs16.readFileSync(profilePath, "utf-8"));
23595
23626
  const describe = typeof raw.describe === "string" ? raw.describe : "";
23596
23627
  const firstSentence = describe.split(/(?<=[.!?])\s+/, 1)[0] ?? "";
23597
23628
  entries.push({ name, describe: firstSentence.trim() });
@@ -23699,7 +23730,7 @@ async function runChatTurn(opts) {
23699
23730
  quiet: opts.quiet,
23700
23731
  additionalDirectories: [
23701
23732
  taskArtifactsPaths.absDir,
23702
- ...Array.from(new Set(imagePaths.map((p2) => path15.dirname(p2))))
23733
+ ...Array.from(new Set(imagePaths.map((p2) => path17.dirname(p2))))
23703
23734
  ],
23704
23735
  systemPromptAppend: systemPrompt,
23705
23736
  ...opts.reasoningEffort ? { reasoningEffort: opts.reasoningEffort } : {},
@@ -23883,10 +23914,10 @@ async function emit(sink, type, sessionId, suffix, payload) {
23883
23914
  var MEMORY_INDEX_REL = ".kody-engine/runtime/memory/INDEX.md";
23884
23915
  var MAX_INDEX_BYTES = 8e3;
23885
23916
  function readMemoryIndexBlock(cwd) {
23886
- const indexPath = path15.join(cwd, MEMORY_INDEX_REL);
23917
+ const indexPath = path17.join(cwd, MEMORY_INDEX_REL);
23887
23918
  let raw;
23888
23919
  try {
23889
- raw = fs14.readFileSync(indexPath, "utf-8");
23920
+ raw = fs16.readFileSync(indexPath, "utf-8");
23890
23921
  } catch {
23891
23922
  return "";
23892
23923
  }
@@ -23906,17 +23937,17 @@ _\u2026 (memory index truncated; use recall_search to read more)_` : trimmed;
23906
23937
  var CONTEXT_DIR_REL = ".kody-engine/runtime/context";
23907
23938
  var MAX_CONTEXT_BYTES = 12e3;
23908
23939
  function readContextBlock(cwd) {
23909
- const dir = path15.join(cwd, CONTEXT_DIR_REL);
23940
+ const dir = path17.join(cwd, CONTEXT_DIR_REL);
23910
23941
  let files;
23911
23942
  try {
23912
- files = fs14.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
23943
+ files = fs16.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
23913
23944
  } catch {
23914
23945
  return "";
23915
23946
  }
23916
23947
  const sections = [];
23917
23948
  for (const file of files) {
23918
23949
  try {
23919
- const content = fs14.readFileSync(path15.join(dir, file), "utf-8").trim();
23950
+ const content = fs16.readFileSync(path17.join(dir, file), "utf-8").trim();
23920
23951
  if (content) sections.push(`### ${file.replace(/\.md$/, "")}
23921
23952
 
23922
23953
  ${content}`);
@@ -23942,7 +23973,7 @@ var SYSTEM_PROMPT_OVERRIDE_REL = ".kody-engine/runtime/system-prompt.md";
23942
23973
  function readSystemPromptOverride(cwd) {
23943
23974
  let raw;
23944
23975
  try {
23945
- raw = fs14.readFileSync(path15.join(cwd, SYSTEM_PROMPT_OVERRIDE_REL), "utf-8");
23976
+ raw = fs16.readFileSync(path17.join(cwd, SYSTEM_PROMPT_OVERRIDE_REL), "utf-8");
23946
23977
  } catch {
23947
23978
  return null;
23948
23979
  }
@@ -23950,10 +23981,10 @@ function readSystemPromptOverride(cwd) {
23950
23981
  return trimmed.length > 0 ? trimmed : null;
23951
23982
  }
23952
23983
  function readInstructionsBlock(cwd) {
23953
- const instructionsPath = path15.join(cwd, INSTRUCTIONS_REL);
23984
+ const instructionsPath = path17.join(cwd, INSTRUCTIONS_REL);
23954
23985
  let raw;
23955
23986
  try {
23956
- raw = fs14.readFileSync(instructionsPath, "utf-8");
23987
+ raw = fs16.readFileSync(instructionsPath, "utf-8");
23957
23988
  } catch {
23958
23989
  return "";
23959
23990
  }
@@ -23987,15 +24018,15 @@ function resolveBrainDriver(runtime) {
23987
24018
  }
23988
24019
 
23989
24020
  // src/chat/session.ts
23990
- import * as fs15 from "fs";
23991
- import * as path16 from "path";
24021
+ import * as fs17 from "fs";
24022
+ import * as path18 from "path";
23992
24023
  import posixPath3 from "path/posix";
23993
24024
  function sessionFilePath(cwd, sessionId) {
23994
- return path16.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
24025
+ return path18.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
23995
24026
  }
23996
24027
  function readSession(file) {
23997
- if (!fs15.existsSync(file)) return [];
23998
- const raw = fs15.readFileSync(file, "utf-8").trim();
24028
+ if (!fs17.existsSync(file)) return [];
24029
+ const raw = fs17.readFileSync(file, "utf-8").trim();
23999
24030
  if (!raw) return [];
24000
24031
  const turns = [];
24001
24032
  for (const line of raw.split("\n")) {
@@ -24018,8 +24049,8 @@ init_config();
24018
24049
  init_state_backend();
24019
24050
  init_workflowDefinitions();
24020
24051
  import { createHash as createHash2 } from "crypto";
24021
- import * as fs17 from "fs";
24022
- import * as path18 from "path";
24052
+ import * as fs19 from "fs";
24053
+ import * as path20 from "path";
24023
24054
  var SLUG_RE = /^[a-z0-9][a-z0-9_-]{0,127}$/;
24024
24055
  var REPOSITORY_OWNED_NAMESPACES = ["loops"];
24025
24056
  function assertSafeDefinitionPath(filePath) {
@@ -24051,9 +24082,9 @@ function verifyDefinition(definition) {
24051
24082
  }
24052
24083
  function writeBundle(root, bundle) {
24053
24084
  for (const [filePath, contents] of Object.entries(bundle.files)) {
24054
- const target = path18.join(root, filePath);
24055
- fs17.mkdirSync(path18.dirname(target), { recursive: true });
24056
- fs17.writeFileSync(target, contents, "utf8");
24085
+ const target = path20.join(root, filePath);
24086
+ fs19.mkdirSync(path20.dirname(target), { recursive: true });
24087
+ fs19.writeFileSync(target, contents, "utf8");
24057
24088
  }
24058
24089
  }
24059
24090
  function writeDefinition(root, kind, definition) {
@@ -24061,22 +24092,22 @@ function writeDefinition(root, kind, definition) {
24061
24092
  if (kind === "agent") {
24062
24093
  const raw = bundle.files["agent.md"];
24063
24094
  if (typeof raw !== "string") throw new Error(`agent definition ${definition.slug} is missing agent.md`);
24064
- fs17.writeFileSync(path18.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
24095
+ fs19.writeFileSync(path20.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
24065
24096
  return;
24066
24097
  }
24067
24098
  if (kind === "goal") {
24068
- writeBundle(path18.join(root, "goals", definition.slug), bundle);
24099
+ writeBundle(path20.join(root, "goals", definition.slug), bundle);
24069
24100
  return;
24070
24101
  }
24071
24102
  if (kind === "implementation") {
24072
- writeBundle(path18.join(root, "implementations", definition.slug), bundle);
24103
+ writeBundle(path20.join(root, "implementations", definition.slug), bundle);
24073
24104
  return;
24074
24105
  }
24075
24106
  if (kind === "asset") {
24076
- writeBundle(path18.join(root, "shared"), bundle);
24107
+ writeBundle(path20.join(root, "shared"), bundle);
24077
24108
  return;
24078
24109
  }
24079
- writeBundle(path18.join(root, "capabilities", definition.slug), bundle);
24110
+ writeBundle(path20.join(root, "capabilities", definition.slug), bundle);
24080
24111
  }
24081
24112
  function writeWorkflow(root, document) {
24082
24113
  const workflow = normalizeWorkflowDefinition(document.definition);
@@ -24084,28 +24115,28 @@ function writeWorkflow(root, document) {
24084
24115
  const contents = `${JSON.stringify(workflow, null, 2)}
24085
24116
  `;
24086
24117
  const bundle = { schemaVersion: 1, files: { "workflow.json": contents } };
24087
- const target = path18.join(root, workflowDefinitionPath(document.workflowId));
24088
- fs17.mkdirSync(path18.dirname(target), { recursive: true });
24089
- fs17.writeFileSync(target, contents, "utf8");
24118
+ const target = path20.join(root, workflowDefinitionPath(document.workflowId));
24119
+ fs19.mkdirSync(path20.dirname(target), { recursive: true });
24120
+ fs19.writeFileSync(target, contents, "utf8");
24090
24121
  return definitionVersion(bundle);
24091
24122
  }
24092
24123
  function preserveRepositoryDefinitions(root, staging) {
24093
24124
  for (const namespace of REPOSITORY_OWNED_NAMESPACES) {
24094
- const source = path18.join(root, namespace);
24095
- if (!fs17.existsSync(source)) continue;
24096
- fs17.cpSync(source, path18.join(staging, namespace), { recursive: true });
24125
+ const source = path20.join(root, namespace);
24126
+ if (!fs19.existsSync(source)) continue;
24127
+ fs19.cpSync(source, path20.join(staging, namespace), { recursive: true });
24097
24128
  }
24098
24129
  }
24099
24130
  async function hydrateDefinitions(options) {
24100
- const root = path18.join(options.cwd, ".kody-engine", "definitions");
24131
+ const root = path20.join(options.cwd, ".kody-engine", "definitions");
24101
24132
  const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
24102
- fs17.rmSync(staging, { recursive: true, force: true });
24103
- fs17.mkdirSync(path18.join(staging, "agents"), { recursive: true });
24104
- fs17.mkdirSync(path18.join(staging, "capabilities"), { recursive: true });
24105
- fs17.mkdirSync(path18.join(staging, "goals"), { recursive: true });
24106
- fs17.mkdirSync(path18.join(staging, "implementations"), { recursive: true });
24107
- fs17.mkdirSync(path18.join(staging, "shared"), { recursive: true });
24108
- fs17.mkdirSync(path18.join(staging, "workflows"), { recursive: true });
24133
+ fs19.rmSync(staging, { recursive: true, force: true });
24134
+ fs19.mkdirSync(path20.join(staging, "agents"), { recursive: true });
24135
+ fs19.mkdirSync(path20.join(staging, "capabilities"), { recursive: true });
24136
+ fs19.mkdirSync(path20.join(staging, "goals"), { recursive: true });
24137
+ fs19.mkdirSync(path20.join(staging, "implementations"), { recursive: true });
24138
+ fs19.mkdirSync(path20.join(staging, "shared"), { recursive: true });
24139
+ fs19.mkdirSync(path20.join(staging, "workflows"), { recursive: true });
24109
24140
  try {
24110
24141
  const [capabilities, agents, goals, implementations, assets, workflows] = await Promise.all([
24111
24142
  options.backend.listDefinitions(options.tenantId, "capability"),
@@ -24146,13 +24177,13 @@ async function hydrateDefinitions(options) {
24146
24177
  hydratedAt: (/* @__PURE__ */ new Date()).toISOString(),
24147
24178
  versions: Object.fromEntries(Object.entries(versions).sort(([left], [right]) => left.localeCompare(right)))
24148
24179
  };
24149
- fs17.writeFileSync(path18.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
24180
+ fs19.writeFileSync(path20.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
24150
24181
  `, "utf8");
24151
- fs17.rmSync(root, { recursive: true, force: true });
24152
- fs17.renameSync(staging, root);
24182
+ fs19.rmSync(root, { recursive: true, force: true });
24183
+ fs19.renameSync(staging, root);
24153
24184
  return { root, tenantId: options.tenantId, versions: manifest.versions };
24154
24185
  } catch (error) {
24155
- fs17.rmSync(staging, { recursive: true, force: true });
24186
+ fs19.rmSync(staging, { recursive: true, force: true });
24156
24187
  throw error;
24157
24188
  }
24158
24189
  }
@@ -24304,7 +24335,7 @@ init_definition_paths();
24304
24335
 
24305
24336
  // src/dispatch.ts
24306
24337
  init_config();
24307
- import * as fs18 from "fs";
24338
+ import * as fs20 from "fs";
24308
24339
 
24309
24340
  // src/cron-match.ts
24310
24341
  var FIELD_BOUNDS = [
@@ -24411,10 +24442,10 @@ function autoDispatch(opts) {
24411
24442
  }
24412
24443
  const eventName = process.env.GITHUB_EVENT_NAME;
24413
24444
  const eventPath = process.env.GITHUB_EVENT_PATH;
24414
- if (!eventName || !eventPath || !fs18.existsSync(eventPath)) return null;
24445
+ if (!eventName || !eventPath || !fs20.existsSync(eventPath)) return null;
24415
24446
  let event = {};
24416
24447
  try {
24417
- event = JSON.parse(fs18.readFileSync(eventPath, "utf-8"));
24448
+ event = JSON.parse(fs20.readFileSync(eventPath, "utf-8"));
24418
24449
  } catch {
24419
24450
  return null;
24420
24451
  }
@@ -24538,7 +24569,7 @@ function autoDispatchTyped(opts) {
24538
24569
  if (legacy) return { kind: "route", ...legacy };
24539
24570
  const eventName = process.env.GITHUB_EVENT_NAME;
24540
24571
  const eventPath = process.env.GITHUB_EVENT_PATH;
24541
- if (!eventName || !eventPath || !fs18.existsSync(eventPath)) {
24572
+ if (!eventName || !eventPath || !fs20.existsSync(eventPath)) {
24542
24573
  return { kind: "silent", reason: "no GHA event context" };
24543
24574
  }
24544
24575
  if (eventName !== "issue_comment") {
@@ -24546,7 +24577,7 @@ function autoDispatchTyped(opts) {
24546
24577
  }
24547
24578
  let event = {};
24548
24579
  try {
24549
- event = JSON.parse(fs18.readFileSync(eventPath, "utf-8"));
24580
+ event = JSON.parse(fs20.readFileSync(eventPath, "utf-8"));
24550
24581
  } catch {
24551
24582
  return { kind: "silent", reason: "GHA event payload unreadable" };
24552
24583
  }
@@ -24600,7 +24631,7 @@ function dispatchScheduledWatches(opts) {
24600
24631
  for (const exe of listRuntimeProfilesForCwd(opts?.cwd ?? process.cwd())) {
24601
24632
  let raw;
24602
24633
  try {
24603
- raw = fs18.readFileSync(exe.profilePath, "utf-8");
24634
+ raw = fs20.readFileSync(exe.profilePath, "utf-8");
24604
24635
  } catch {
24605
24636
  continue;
24606
24637
  }