@kody-ade/kody-engine 0.4.507 → 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 +373 -351
- package/package.json +1 -1
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.
|
|
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",
|
|
@@ -620,8 +620,9 @@ function formatResult(msg) {
|
|
|
620
620
|
function summarizeToolInput(toolName, input = {}) {
|
|
621
621
|
if (toolName === "Agent") {
|
|
622
622
|
const agent = summarizeSingleLineValue(input.subagent_type, "unknown", 80);
|
|
623
|
-
const
|
|
624
|
-
|
|
623
|
+
const requestedModel = summarizeSingleLineValue(input.model, "inherit", 80);
|
|
624
|
+
const ignoredOverride = requestedModel === "inherit" ? "" : ` (ignored override=${requestedModel})`;
|
|
625
|
+
return `: ${agent} model=inherit${ignoredOverride}`;
|
|
625
626
|
}
|
|
626
627
|
if (toolName === "Bash" && typeof input.command === "string") {
|
|
627
628
|
const cmd = input.command.split("\n")[0];
|
|
@@ -698,6 +699,178 @@ var init_runtimePaths = __esm({
|
|
|
698
699
|
}
|
|
699
700
|
});
|
|
700
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
|
+
|
|
701
874
|
// src/events.ts
|
|
702
875
|
var events_exports = {};
|
|
703
876
|
__export(events_exports, {
|
|
@@ -708,8 +881,8 @@ __export(events_exports, {
|
|
|
708
881
|
resolveRunId: () => resolveRunId
|
|
709
882
|
});
|
|
710
883
|
import * as crypto from "crypto";
|
|
711
|
-
import * as
|
|
712
|
-
import * as
|
|
884
|
+
import * as fs5 from "fs";
|
|
885
|
+
import * as path6 from "path";
|
|
713
886
|
function resolveRunId() {
|
|
714
887
|
if (process.env.KODY_RUN_ID) {
|
|
715
888
|
cachedRunId = process.env.KODY_RUN_ID;
|
|
@@ -742,16 +915,16 @@ function emitEvent(cwd, ev) {
|
|
|
742
915
|
...ev
|
|
743
916
|
};
|
|
744
917
|
const file = eventsPath(cwd, runId);
|
|
745
|
-
|
|
746
|
-
|
|
918
|
+
fs5.mkdirSync(path6.dirname(file), { recursive: true });
|
|
919
|
+
fs5.appendFileSync(file, `${JSON.stringify(fullEvent)}
|
|
747
920
|
`);
|
|
748
921
|
} catch {
|
|
749
922
|
}
|
|
750
923
|
}
|
|
751
924
|
function readEvents(cwd, runId) {
|
|
752
925
|
const file = eventsPath(cwd, runId);
|
|
753
|
-
if (!
|
|
754
|
-
const lines =
|
|
926
|
+
if (!fs5.existsSync(file)) return [];
|
|
927
|
+
const lines = fs5.readFileSync(file, "utf-8").split("\n");
|
|
755
928
|
const out = [];
|
|
756
929
|
for (const line of lines) {
|
|
757
930
|
const trimmed = line.trim();
|
|
@@ -765,10 +938,10 @@ function readEvents(cwd, runId) {
|
|
|
765
938
|
}
|
|
766
939
|
function listRuns(cwd) {
|
|
767
940
|
const runsDir = runtimeStatePath(cwd, "agent-runs");
|
|
768
|
-
if (!
|
|
769
|
-
return
|
|
941
|
+
if (!fs5.existsSync(runsDir)) return [];
|
|
942
|
+
return fs5.readdirSync(runsDir).filter((name) => {
|
|
770
943
|
try {
|
|
771
|
-
return
|
|
944
|
+
return fs5.statSync(path6.join(runsDir, name)).isDirectory();
|
|
772
945
|
} catch {
|
|
773
946
|
return false;
|
|
774
947
|
}
|
|
@@ -1690,8 +1863,8 @@ var init_issue = __esm({
|
|
|
1690
1863
|
});
|
|
1691
1864
|
|
|
1692
1865
|
// src/capabilityFolders.ts
|
|
1693
|
-
import * as
|
|
1694
|
-
import * as
|
|
1866
|
+
import * as fs6 from "fs";
|
|
1867
|
+
import * as path7 from "path";
|
|
1695
1868
|
function capabilityOutputConditionPaths(config) {
|
|
1696
1869
|
if (config.outputSchema) {
|
|
1697
1870
|
return new Set(schemaPropertyPaths(config.outputSchema, "result"));
|
|
@@ -1706,32 +1879,32 @@ function capabilityOutputConditionPaths(config) {
|
|
|
1706
1879
|
]);
|
|
1707
1880
|
}
|
|
1708
1881
|
function listCapabilityFolderSlugs(absDir) {
|
|
1709
|
-
if (!
|
|
1882
|
+
if (!fs6.existsSync(absDir)) return [];
|
|
1710
1883
|
let entries;
|
|
1711
1884
|
try {
|
|
1712
|
-
entries =
|
|
1885
|
+
entries = fs6.readdirSync(absDir, { withFileTypes: true });
|
|
1713
1886
|
} catch {
|
|
1714
1887
|
return [];
|
|
1715
1888
|
}
|
|
1716
|
-
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(
|
|
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();
|
|
1717
1890
|
}
|
|
1718
1891
|
function isCapabilityFolder(dir) {
|
|
1719
|
-
if (!
|
|
1720
|
-
const entries =
|
|
1892
|
+
if (!fs6.existsSync(path7.join(dir, CAPABILITY_BODY_FILE))) return false;
|
|
1893
|
+
const entries = fs6.readdirSync(dir, { withFileTypes: true });
|
|
1721
1894
|
return entries.every(
|
|
1722
1895
|
(entry) => entry.name === CAPABILITY_BODY_FILE || entry.name === CAPABILITY_CONTRACT_FILE || entry.isDirectory() && (entry.name === "skills" || entry.name === "tools")
|
|
1723
1896
|
);
|
|
1724
1897
|
}
|
|
1725
1898
|
function readCapabilityFolder(root, slug) {
|
|
1726
|
-
const dir =
|
|
1727
|
-
const bodyPath =
|
|
1728
|
-
const contractPath =
|
|
1729
|
-
if (!
|
|
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;
|
|
1730
1903
|
if (!isCapabilityFolder(dir)) return null;
|
|
1731
1904
|
try {
|
|
1732
|
-
const rawBody =
|
|
1733
|
-
const contract =
|
|
1734
|
-
if (contract?.execution === "script" && !isRegularFile(
|
|
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"))) {
|
|
1735
1908
|
throw new Error('script-backed Capability requires a regular "tools/run.sh" file');
|
|
1736
1909
|
}
|
|
1737
1910
|
const { title, body } = parseCapabilityBody(rawBody, slug);
|
|
@@ -1802,7 +1975,7 @@ function parseCapabilityContract(raw) {
|
|
|
1802
1975
|
}
|
|
1803
1976
|
function isRegularFile(filePath) {
|
|
1804
1977
|
try {
|
|
1805
|
-
const stat =
|
|
1978
|
+
const stat = fs6.lstatSync(filePath);
|
|
1806
1979
|
return stat.isFile() && !stat.isSymbolicLink();
|
|
1807
1980
|
} catch {
|
|
1808
1981
|
return false;
|
|
@@ -1961,51 +2134,51 @@ var init_capabilityFolders = __esm({
|
|
|
1961
2134
|
});
|
|
1962
2135
|
|
|
1963
2136
|
// src/definition-paths.ts
|
|
1964
|
-
import * as
|
|
1965
|
-
import * as
|
|
2137
|
+
import * as fs7 from "fs";
|
|
2138
|
+
import * as path8 from "path";
|
|
1966
2139
|
function definitionsRoot(cwd = process.cwd()) {
|
|
1967
2140
|
const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
|
|
1968
2141
|
const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
|
|
1969
|
-
if (override && overrideCwd &&
|
|
1970
|
-
return storeCatalogRoot(
|
|
2142
|
+
if (override && overrideCwd && path8.resolve(cwd) === path8.resolve(overrideCwd)) {
|
|
2143
|
+
return storeCatalogRoot(path8.resolve(override));
|
|
1971
2144
|
}
|
|
1972
|
-
const hydrated =
|
|
1973
|
-
if (
|
|
1974
|
-
return override ? storeCatalogRoot(
|
|
2145
|
+
const hydrated = path8.join(cwd, ".kody-engine", "definitions");
|
|
2146
|
+
if (fs7.existsSync(hydrated)) return hydrated;
|
|
2147
|
+
return override ? storeCatalogRoot(path8.resolve(override)) : hydrated;
|
|
1975
2148
|
}
|
|
1976
2149
|
function hasExplicitDefinitionsRoot(cwd = process.cwd(), env = process.env) {
|
|
1977
2150
|
const root = env.KODY_DEFINITIONS_ROOT?.trim();
|
|
1978
2151
|
const rootCwd = env.KODY_DEFINITIONS_ROOT_CWD?.trim();
|
|
1979
|
-
return Boolean(root && rootCwd &&
|
|
2152
|
+
return Boolean(root && rootCwd && path8.resolve(cwd) === path8.resolve(rootCwd));
|
|
1980
2153
|
}
|
|
1981
2154
|
function capabilitiesRoot(cwd = process.cwd()) {
|
|
1982
|
-
return storeAssetRoot(cwd, "capabilities") ??
|
|
2155
|
+
return storeAssetRoot(cwd, "capabilities") ?? path8.join(definitionsRoot(cwd), "capabilities");
|
|
1983
2156
|
}
|
|
1984
2157
|
function implementationsRoot(cwd = process.cwd()) {
|
|
1985
|
-
return
|
|
2158
|
+
return path8.join(definitionsRoot(cwd), "implementations");
|
|
1986
2159
|
}
|
|
1987
2160
|
function agentsRoot(cwd = process.cwd()) {
|
|
1988
|
-
return storeAssetRoot(cwd, "agent") ??
|
|
2161
|
+
return storeAssetRoot(cwd, "agent") ?? path8.join(definitionsRoot(cwd), "agents");
|
|
1989
2162
|
}
|
|
1990
2163
|
function storeCatalogRoot(root) {
|
|
1991
2164
|
const manifest = readStoreManifest(root);
|
|
1992
|
-
const roots = ["capabilities", "workflows", "loops"].map((kind) => manifest?.assetRoots?.[kind]).filter((value) => typeof value === "string" && Boolean(value.trim())).map((value) =>
|
|
1993
|
-
return roots.length === 3 && new Set(roots).size === 1 ?
|
|
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;
|
|
1994
2167
|
}
|
|
1995
2168
|
function storeAssetRoot(cwd, kind) {
|
|
1996
2169
|
const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
|
|
1997
2170
|
if (!override) return null;
|
|
1998
2171
|
const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
|
|
1999
|
-
if (overrideCwd &&
|
|
2000
|
-
const root =
|
|
2172
|
+
if (overrideCwd && path8.resolve(cwd) !== path8.resolve(overrideCwd)) return null;
|
|
2173
|
+
const root = path8.resolve(override);
|
|
2001
2174
|
const configured = readStoreManifest(root)?.assetRoots?.[kind];
|
|
2002
|
-
return typeof configured === "string" && configured.trim() ?
|
|
2175
|
+
return typeof configured === "string" && configured.trim() ? path8.join(root, configured) : null;
|
|
2003
2176
|
}
|
|
2004
2177
|
function readStoreManifest(root) {
|
|
2005
|
-
const file =
|
|
2006
|
-
if (!
|
|
2178
|
+
const file = path8.join(root, "kody-store.json");
|
|
2179
|
+
if (!fs7.existsSync(file)) return null;
|
|
2007
2180
|
try {
|
|
2008
|
-
return JSON.parse(
|
|
2181
|
+
return JSON.parse(fs7.readFileSync(file, "utf8"));
|
|
2009
2182
|
} catch {
|
|
2010
2183
|
return null;
|
|
2011
2184
|
}
|
|
@@ -2017,32 +2190,32 @@ var init_definition_paths = __esm({
|
|
|
2017
2190
|
});
|
|
2018
2191
|
|
|
2019
2192
|
// src/registry.ts
|
|
2020
|
-
import * as
|
|
2021
|
-
import * as
|
|
2193
|
+
import * as fs8 from "fs";
|
|
2194
|
+
import * as path9 from "path";
|
|
2022
2195
|
function getImplementationsRoot() {
|
|
2023
|
-
const here =
|
|
2196
|
+
const here = path9.dirname(new URL(import.meta.url).pathname);
|
|
2024
2197
|
const candidates = [
|
|
2025
|
-
|
|
2198
|
+
path9.join(here, "implementations"),
|
|
2026
2199
|
// dev: src/
|
|
2027
|
-
|
|
2200
|
+
path9.join(here, "..", "implementations"),
|
|
2028
2201
|
// built: dist/bin → dist/implementations
|
|
2029
|
-
|
|
2202
|
+
path9.join(here, "..", "src", "implementations")
|
|
2030
2203
|
// fallback
|
|
2031
2204
|
];
|
|
2032
2205
|
for (const c of candidates) {
|
|
2033
|
-
if (
|
|
2206
|
+
if (fs8.existsSync(c) && fs8.statSync(c).isDirectory()) return c;
|
|
2034
2207
|
}
|
|
2035
2208
|
return candidates[0];
|
|
2036
2209
|
}
|
|
2037
2210
|
function getRuntimeServicesRoot() {
|
|
2038
|
-
const here =
|
|
2211
|
+
const here = path9.dirname(new URL(import.meta.url).pathname);
|
|
2039
2212
|
const candidates = [
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2213
|
+
path9.join(here, "runtime-services"),
|
|
2214
|
+
path9.join(here, "..", "runtime-services"),
|
|
2215
|
+
path9.join(here, "..", "src", "runtime-services")
|
|
2043
2216
|
];
|
|
2044
2217
|
for (const candidate of candidates) {
|
|
2045
|
-
if (
|
|
2218
|
+
if (fs8.existsSync(candidate) && fs8.statSync(candidate).isDirectory()) return candidate;
|
|
2046
2219
|
}
|
|
2047
2220
|
return candidates[0];
|
|
2048
2221
|
}
|
|
@@ -2050,17 +2223,17 @@ function getProjectCapabilitiesRoot() {
|
|
|
2050
2223
|
return capabilitiesRoot();
|
|
2051
2224
|
}
|
|
2052
2225
|
function getBuiltinCapabilitiesRoot() {
|
|
2053
|
-
const here =
|
|
2226
|
+
const here = path9.dirname(new URL(import.meta.url).pathname);
|
|
2054
2227
|
const candidates = [
|
|
2055
|
-
|
|
2228
|
+
path9.join(here, "capabilities"),
|
|
2056
2229
|
// dev: src/
|
|
2057
|
-
|
|
2230
|
+
path9.join(here, "..", "capabilities"),
|
|
2058
2231
|
// built: dist/bin → dist/capabilities
|
|
2059
|
-
|
|
2232
|
+
path9.join(here, "..", "src", "capabilities")
|
|
2060
2233
|
// fallback
|
|
2061
2234
|
];
|
|
2062
2235
|
for (const c of candidates) {
|
|
2063
|
-
if (
|
|
2236
|
+
if (fs8.existsSync(c) && fs8.statSync(c).isDirectory()) return c;
|
|
2064
2237
|
}
|
|
2065
2238
|
return candidates[0];
|
|
2066
2239
|
}
|
|
@@ -2083,14 +2256,14 @@ function listImplementations(roots = getImplementationRoots()) {
|
|
|
2083
2256
|
const seen = /* @__PURE__ */ new Set();
|
|
2084
2257
|
const out = [];
|
|
2085
2258
|
for (const root of rootList) {
|
|
2086
|
-
if (!
|
|
2259
|
+
if (!fs8.existsSync(root)) continue;
|
|
2087
2260
|
const requireImplementationProfile = isCapabilityRoot(root);
|
|
2088
|
-
const entries =
|
|
2261
|
+
const entries = fs8.readdirSync(root, { withFileTypes: true });
|
|
2089
2262
|
for (const ent of entries) {
|
|
2090
2263
|
if (!ent.isDirectory()) continue;
|
|
2091
2264
|
if (seen.has(ent.name)) continue;
|
|
2092
2265
|
const profilePath = implementationRuntimePath(root, ent.name);
|
|
2093
|
-
if (
|
|
2266
|
+
if (fs8.existsSync(profilePath) && fs8.statSync(profilePath).isFile() && isImplementationProfile(profilePath, requireImplementationProfile)) {
|
|
2094
2267
|
out.push({ name: ent.name, profilePath });
|
|
2095
2268
|
seen.add(ent.name);
|
|
2096
2269
|
}
|
|
@@ -2110,7 +2283,7 @@ function resolveImplementationCandidates(name, roots = getRuntimeProfileRootsFor
|
|
|
2110
2283
|
const out = [];
|
|
2111
2284
|
for (const root of rootList) {
|
|
2112
2285
|
const profilePath = implementationRuntimePath(root, name);
|
|
2113
|
-
if (
|
|
2286
|
+
if (fs8.existsSync(profilePath) && fs8.statSync(profilePath).isFile() && isImplementationProfile(profilePath, isCapabilityRoot(root))) {
|
|
2114
2287
|
out.push(profilePath);
|
|
2115
2288
|
}
|
|
2116
2289
|
}
|
|
@@ -2179,7 +2352,7 @@ function implementationDeclaresInput(implementation, inputName, cwd = process.cw
|
|
|
2179
2352
|
const profilePath = resolveImplementation(implementation, getRuntimeProfileRootsForCwd(cwd));
|
|
2180
2353
|
if (!profilePath) return false;
|
|
2181
2354
|
try {
|
|
2182
|
-
const document = JSON.parse(
|
|
2355
|
+
const document = JSON.parse(fs8.readFileSync(profilePath, "utf-8"));
|
|
2183
2356
|
const raw = document.config ?? document;
|
|
2184
2357
|
if (!Array.isArray(raw.inputs)) return false;
|
|
2185
2358
|
return raw.inputs.some((entry) => {
|
|
@@ -2195,29 +2368,29 @@ function isSafeName(name) {
|
|
|
2195
2368
|
return /^[a-z][a-z0-9-]*$/.test(name) && !name.includes("..");
|
|
2196
2369
|
}
|
|
2197
2370
|
function isCapabilityRoot(root) {
|
|
2198
|
-
const normalized =
|
|
2199
|
-
if (
|
|
2371
|
+
const normalized = path9.normalize(root);
|
|
2372
|
+
if (path9.basename(normalized) === "capabilities") return true;
|
|
2200
2373
|
const knownRoots = [getProjectCapabilitiesRoot(), getBuiltinCapabilitiesRoot()];
|
|
2201
|
-
return knownRoots.some((candidate) => candidate &&
|
|
2374
|
+
return knownRoots.some((candidate) => candidate && path9.normalize(candidate) === normalized);
|
|
2202
2375
|
}
|
|
2203
2376
|
function implementationRuntimePath(root, name) {
|
|
2204
|
-
const runtimePath =
|
|
2205
|
-
if (
|
|
2206
|
-
const internalProfilePath =
|
|
2207
|
-
if (
|
|
2208
|
-
return
|
|
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);
|
|
2209
2382
|
}
|
|
2210
2383
|
function isImplementationProfile(profilePath, requireImplementationProfile) {
|
|
2211
2384
|
if (!requireImplementationProfile) return true;
|
|
2212
2385
|
try {
|
|
2213
|
-
const raw = JSON.parse(
|
|
2386
|
+
const raw = JSON.parse(fs8.readFileSync(profilePath, "utf-8"));
|
|
2214
2387
|
return typeof raw.role === "string" && PUBLIC_IMPLEMENTATION_ROLES.has(raw.role);
|
|
2215
2388
|
} catch {
|
|
2216
2389
|
return false;
|
|
2217
2390
|
}
|
|
2218
2391
|
}
|
|
2219
2392
|
function listFolderCapabilityActions(root, source) {
|
|
2220
|
-
if (!
|
|
2393
|
+
if (!fs8.existsSync(root) || !fs8.statSync(root).isDirectory()) return [];
|
|
2221
2394
|
const out = [];
|
|
2222
2395
|
for (const slug of listCapabilityFolderSlugs(root)) {
|
|
2223
2396
|
if (!isSafeName(slug)) continue;
|
|
@@ -2249,7 +2422,7 @@ function hasUnresolvedExplicitImplementation(capability, implementation) {
|
|
|
2249
2422
|
return resolveImplementation(implementation) === null;
|
|
2250
2423
|
}
|
|
2251
2424
|
function listBuiltinCapabilityActions(root = getBuiltinCapabilitiesRoot()) {
|
|
2252
|
-
if (!
|
|
2425
|
+
if (!fs8.existsSync(root) || !fs8.statSync(root).isDirectory()) return [];
|
|
2253
2426
|
const out = [];
|
|
2254
2427
|
for (const slug of listCapabilityFolderSlugs(root)) {
|
|
2255
2428
|
if (!isSafeName(slug)) continue;
|
|
@@ -2274,7 +2447,7 @@ function getProfileInputs(name, roots = getImplementationRoots()) {
|
|
|
2274
2447
|
const profilePath = resolveImplementation(name, roots);
|
|
2275
2448
|
if (!profilePath) return null;
|
|
2276
2449
|
try {
|
|
2277
|
-
const document = JSON.parse(
|
|
2450
|
+
const document = JSON.parse(fs8.readFileSync(profilePath, "utf-8"));
|
|
2278
2451
|
if (!document || typeof document !== "object") return [];
|
|
2279
2452
|
const raw = "config" in document && document.config && typeof document.config === "object" ? document.config : document;
|
|
2280
2453
|
if (!Array.isArray(raw.inputs)) return [];
|
|
@@ -3312,8 +3485,8 @@ var init_capabilityMcp = __esm({
|
|
|
3312
3485
|
|
|
3313
3486
|
// src/repoWorkspace.ts
|
|
3314
3487
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
3315
|
-
import * as
|
|
3316
|
-
import * as
|
|
3488
|
+
import * as fs9 from "fs";
|
|
3489
|
+
import * as path10 from "path";
|
|
3317
3490
|
function buildCloneProcess(repo, token, baseEnv = process.env) {
|
|
3318
3491
|
const url = `https://github.com/${repo}.git`;
|
|
3319
3492
|
const env = { ...baseEnv };
|
|
@@ -3328,10 +3501,10 @@ function buildCloneProcess(repo, token, baseEnv = process.env) {
|
|
|
3328
3501
|
async function resolveAndClone(reposRoot, repo, repoToken, cloneRepo) {
|
|
3329
3502
|
const name = repo?.trim();
|
|
3330
3503
|
if (!name || !REPO_RE.test(name)) return null;
|
|
3331
|
-
const root =
|
|
3332
|
-
const dir =
|
|
3333
|
-
if (dir !== root && !dir.startsWith(root +
|
|
3334
|
-
if (
|
|
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;
|
|
3335
3508
|
const inflight = repoClones.get(dir);
|
|
3336
3509
|
if (inflight) {
|
|
3337
3510
|
await inflight;
|
|
@@ -3363,7 +3536,7 @@ var init_repoWorkspace = __esm({
|
|
|
3363
3536
|
repoClones = /* @__PURE__ */ new Map();
|
|
3364
3537
|
GIT_CREDENTIAL_HELPER = `!f() { if [ "$1" = get ] && [ -n "$GITHUB_TOKEN" ]; then printf '%s\\n' username=x-access-token "password=$GITHUB_TOKEN"; fi; }; f`;
|
|
3365
3538
|
defaultCloneRepo = (repo, token, dir) => {
|
|
3366
|
-
|
|
3539
|
+
fs9.mkdirSync(path10.dirname(dir), { recursive: true });
|
|
3367
3540
|
const clone = buildCloneProcess(repo, token);
|
|
3368
3541
|
return new Promise((resolve19, reject) => {
|
|
3369
3542
|
const child = spawn2("git", ["clone", "--depth=1", clone.url, dir], {
|
|
@@ -3457,8 +3630,8 @@ var init_fetchRepoMcp = __esm({
|
|
|
3457
3630
|
});
|
|
3458
3631
|
|
|
3459
3632
|
// src/agent.ts
|
|
3460
|
-
import * as
|
|
3461
|
-
import * as
|
|
3633
|
+
import * as fs10 from "fs";
|
|
3634
|
+
import * as path11 from "path";
|
|
3462
3635
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
3463
3636
|
function classifySubtype(subtype) {
|
|
3464
3637
|
if (!subtype) return "generic_failed";
|
|
@@ -3527,8 +3700,8 @@ function buildAgentEnvironment(baseEnv, repoToken, requestEnvironment) {
|
|
|
3527
3700
|
}
|
|
3528
3701
|
async function runAgent(opts) {
|
|
3529
3702
|
const ndjsonDir = opts.ndjsonDir ?? agentRunDir(opts.cwd);
|
|
3530
|
-
|
|
3531
|
-
const ndjsonPath =
|
|
3703
|
+
fs10.mkdirSync(ndjsonDir, { recursive: true });
|
|
3704
|
+
const ndjsonPath = path11.join(ndjsonDir, "last-run.jsonl");
|
|
3532
3705
|
const env = buildAgentEnvironment(process.env, opts.repoToken, opts.environment);
|
|
3533
3706
|
if (opts.litellmUrl) {
|
|
3534
3707
|
env.ANTHROPIC_BASE_URL = opts.litellmUrl;
|
|
@@ -3547,7 +3720,7 @@ async function runAgent(opts) {
|
|
|
3547
3720
|
for (let attempt = 0; ; attempt++) {
|
|
3548
3721
|
let ndjsonWriteFailed = false;
|
|
3549
3722
|
let ndjsonWriteError;
|
|
3550
|
-
const fullLog =
|
|
3723
|
+
const fullLog = fs10.createWriteStream(ndjsonPath, { flags: "w" });
|
|
3551
3724
|
fullLog.on("error", (err) => {
|
|
3552
3725
|
ndjsonWriteFailed = true;
|
|
3553
3726
|
ndjsonWriteError = err instanceof Error ? err.message : String(err);
|
|
@@ -3571,7 +3744,15 @@ async function runAgent(opts) {
|
|
|
3571
3744
|
// opt-in tools like fetch_repo can be appended below.
|
|
3572
3745
|
allowedTools: [...opts.allowedToolsOverride ?? DEFAULT_ALLOWED_TOOLS],
|
|
3573
3746
|
permissionMode: opts.permissionModeOverride ?? "acceptEdits",
|
|
3574
|
-
env
|
|
3747
|
+
env,
|
|
3748
|
+
hooks: {
|
|
3749
|
+
PreToolUse: [
|
|
3750
|
+
{
|
|
3751
|
+
matcher: "Agent",
|
|
3752
|
+
hooks: [enforceSubagentModelInheritance]
|
|
3753
|
+
}
|
|
3754
|
+
]
|
|
3755
|
+
}
|
|
3575
3756
|
};
|
|
3576
3757
|
const additionalDirectories = new Set(opts.additionalDirectories ?? []);
|
|
3577
3758
|
const mcpEntries = [];
|
|
@@ -3902,6 +4083,7 @@ var init_agent = __esm({
|
|
|
3902
4083
|
init_config();
|
|
3903
4084
|
init_format();
|
|
3904
4085
|
init_runtimePaths();
|
|
4086
|
+
init_subagents();
|
|
3905
4087
|
DEFAULT_ALLOWED_TOOLS = ["Bash", "Edit", "Read", "Write", "Glob", "Grep"];
|
|
3906
4088
|
DEFAULT_TURN_TIMEOUT_MS = 6e5;
|
|
3907
4089
|
MAX_CONNECTION_RETRIES = 2;
|
|
@@ -3920,8 +4102,8 @@ var init_agent = __esm({
|
|
|
3920
4102
|
});
|
|
3921
4103
|
|
|
3922
4104
|
// src/agents.ts
|
|
3923
|
-
import * as
|
|
3924
|
-
import * as
|
|
4105
|
+
import * as fs11 from "fs";
|
|
4106
|
+
import * as path12 from "path";
|
|
3925
4107
|
function stripFrontmatter(raw) {
|
|
3926
4108
|
const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
|
|
3927
4109
|
return (match ? match[1] : raw).trim();
|
|
@@ -3929,9 +4111,9 @@ function stripFrontmatter(raw) {
|
|
|
3929
4111
|
function loadAgentIdentity(cwd, slug, agentsDir = agentsRoot(cwd)) {
|
|
3930
4112
|
const trimmed = slug.trim();
|
|
3931
4113
|
if (!trimmed) throw new Error("loadAgentIdentity: empty agent slug");
|
|
3932
|
-
const agentPath =
|
|
3933
|
-
if (
|
|
3934
|
-
const body = stripFrontmatter(
|
|
4114
|
+
const agentPath = resolveAgentFile2(cwd, trimmed, agentsDir);
|
|
4115
|
+
if (fs11.existsSync(agentPath)) {
|
|
4116
|
+
const body = stripFrontmatter(fs11.readFileSync(agentPath, "utf-8"));
|
|
3935
4117
|
if (body) return body;
|
|
3936
4118
|
const builtinForEmpty = BUILTIN_AGENTS[trimmed];
|
|
3937
4119
|
if (builtinForEmpty) return builtinForEmpty;
|
|
@@ -3941,9 +4123,9 @@ function loadAgentIdentity(cwd, slug, agentsDir = agentsRoot(cwd)) {
|
|
|
3941
4123
|
if (builtin) return builtin;
|
|
3942
4124
|
throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
|
|
3943
4125
|
}
|
|
3944
|
-
function
|
|
3945
|
-
const localPath =
|
|
3946
|
-
if (
|
|
4126
|
+
function resolveAgentFile2(cwd, slug, agentsDir = agentsRoot(cwd)) {
|
|
4127
|
+
const localPath = path12.resolve(cwd, agentsDir, `${slug}.md`);
|
|
4128
|
+
if (fs11.existsSync(localPath)) return localPath;
|
|
3947
4129
|
return localPath;
|
|
3948
4130
|
}
|
|
3949
4131
|
function frameAgentIdentity(slug, agent) {
|
|
@@ -3975,14 +4157,14 @@ var init_agents = __esm({
|
|
|
3975
4157
|
});
|
|
3976
4158
|
|
|
3977
4159
|
// src/task-artifacts.ts
|
|
3978
|
-
import
|
|
3979
|
-
import
|
|
4160
|
+
import fs12 from "fs";
|
|
4161
|
+
import path13 from "path";
|
|
3980
4162
|
import posixPath from "path/posix";
|
|
3981
4163
|
function prepareTaskArtifactsDir(cwd, taskId) {
|
|
3982
4164
|
const safeId = String(taskId).replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
3983
4165
|
const absDir = runtimeStatePath(cwd, "task-artifacts", safeId);
|
|
3984
4166
|
const relDir = absDir;
|
|
3985
|
-
|
|
4167
|
+
fs12.mkdirSync(absDir, { recursive: true });
|
|
3986
4168
|
return { taskId: safeId, absDir, relDir };
|
|
3987
4169
|
}
|
|
3988
4170
|
function initializeTaskArtifacts(artifacts, metadata = { taskType: "job" }) {
|
|
@@ -4012,16 +4194,16 @@ function initializeTaskArtifacts(artifacts, metadata = { taskType: "job" }) {
|
|
|
4012
4194
|
"handoff-notes.md": "Baseline handoff: the agent did not provide additional notes.\n"
|
|
4013
4195
|
};
|
|
4014
4196
|
for (const file of TASK_ARTIFACT_FILES) {
|
|
4015
|
-
const full =
|
|
4016
|
-
if (!
|
|
4197
|
+
const full = path13.join(artifacts.absDir, file);
|
|
4198
|
+
if (!fs12.existsSync(full)) fs12.writeFileSync(full, defaults[file], "utf8");
|
|
4017
4199
|
}
|
|
4018
4200
|
}
|
|
4019
4201
|
function verifyTaskArtifacts(absDir) {
|
|
4020
4202
|
const missing = [];
|
|
4021
4203
|
for (const name of TASK_ARTIFACT_FILES) {
|
|
4022
|
-
const full =
|
|
4204
|
+
const full = path13.join(absDir, name);
|
|
4023
4205
|
try {
|
|
4024
|
-
const stat =
|
|
4206
|
+
const stat = fs12.statSync(full);
|
|
4025
4207
|
if (!stat.isFile() || stat.size === 0) missing.push(name);
|
|
4026
4208
|
} catch {
|
|
4027
4209
|
missing.push(name);
|
|
@@ -4037,11 +4219,11 @@ async function persistTaskArtifactsToState(config, _cwd, artifacts) {
|
|
|
4037
4219
|
if (hasStateBackendConfig() && tenantId2) {
|
|
4038
4220
|
const backend = createStateBackendFromEnv();
|
|
4039
4221
|
for (const file of TASK_ARTIFACT_FILES) {
|
|
4040
|
-
const full =
|
|
4041
|
-
if (!
|
|
4042
|
-
const stat =
|
|
4222
|
+
const full = path13.join(artifacts.absDir, file);
|
|
4223
|
+
if (!fs12.existsSync(full)) continue;
|
|
4224
|
+
const stat = fs12.statSync(full);
|
|
4043
4225
|
if (!stat.isFile() || stat.size === 0) continue;
|
|
4044
|
-
const content =
|
|
4226
|
+
const content = fs12.readFileSync(full, "utf-8");
|
|
4045
4227
|
const kind = file.replace(/\.(json|md)$/, "");
|
|
4046
4228
|
let doc = content;
|
|
4047
4229
|
if (file.endsWith(".json")) {
|
|
@@ -4402,8 +4584,8 @@ var init_workflowValidation = __esm({
|
|
|
4402
4584
|
});
|
|
4403
4585
|
|
|
4404
4586
|
// src/workflowDefinitions.ts
|
|
4405
|
-
import * as
|
|
4406
|
-
import * as
|
|
4587
|
+
import * as fs18 from "fs";
|
|
4588
|
+
import * as path19 from "path";
|
|
4407
4589
|
function isWorkflowDefinitionId(value) {
|
|
4408
4590
|
return WORKFLOW_ID_PATTERN.test(value);
|
|
4409
4591
|
}
|
|
@@ -4446,12 +4628,12 @@ function readWorkflowDefinition(_config, cwd, id) {
|
|
|
4446
4628
|
const root = cwd ?? process.cwd();
|
|
4447
4629
|
const relativePath = workflowDefinitionPath(id);
|
|
4448
4630
|
const candidates = [
|
|
4449
|
-
|
|
4450
|
-
|
|
4631
|
+
path19.join(root, ".kody-engine", "runtime", relativePath),
|
|
4632
|
+
path19.join(definitionsRoot(root), relativePath)
|
|
4451
4633
|
];
|
|
4452
4634
|
for (const filePath of candidates) {
|
|
4453
|
-
if (!
|
|
4454
|
-
const workflow = parseWorkflowDefinition(
|
|
4635
|
+
if (!fs18.existsSync(filePath)) continue;
|
|
4636
|
+
const workflow = parseWorkflowDefinition(fs18.readFileSync(filePath, "utf8"));
|
|
4455
4637
|
if (workflow) return workflow;
|
|
4456
4638
|
}
|
|
4457
4639
|
return null;
|
|
@@ -4459,7 +4641,7 @@ function readWorkflowDefinition(_config, cwd, id) {
|
|
|
4459
4641
|
function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
|
|
4460
4642
|
return {
|
|
4461
4643
|
slug: id,
|
|
4462
|
-
dir:
|
|
4644
|
+
dir: path19.dirname(source),
|
|
4463
4645
|
profilePath: source,
|
|
4464
4646
|
bodyPath: source,
|
|
4465
4647
|
title: workflow.name,
|
|
@@ -4514,7 +4696,7 @@ var init_workflowDefinitions = __esm({
|
|
|
4514
4696
|
|
|
4515
4697
|
// src/gha.ts
|
|
4516
4698
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
4517
|
-
import * as
|
|
4699
|
+
import * as fs21 from "fs";
|
|
4518
4700
|
function getRunUrl() {
|
|
4519
4701
|
const server = process.env.GITHUB_SERVER_URL;
|
|
4520
4702
|
const repo = process.env.GITHUB_REPOSITORY;
|
|
@@ -4525,10 +4707,10 @@ function getRunUrl() {
|
|
|
4525
4707
|
function reactToTriggerComment(cwd) {
|
|
4526
4708
|
if (process.env.GITHUB_EVENT_NAME !== "issue_comment") return;
|
|
4527
4709
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
4528
|
-
if (!eventPath || !
|
|
4710
|
+
if (!eventPath || !fs21.existsSync(eventPath)) return;
|
|
4529
4711
|
let event = null;
|
|
4530
4712
|
try {
|
|
4531
|
-
event = JSON.parse(
|
|
4713
|
+
event = JSON.parse(fs21.readFileSync(eventPath, "utf-8"));
|
|
4532
4714
|
} catch {
|
|
4533
4715
|
return;
|
|
4534
4716
|
}
|
|
@@ -5109,166 +5291,6 @@ var init_lifecycles = __esm({
|
|
|
5109
5291
|
}
|
|
5110
5292
|
});
|
|
5111
5293
|
|
|
5112
|
-
// src/scripts/buildSyntheticPlugin.ts
|
|
5113
|
-
import * as fs20 from "fs";
|
|
5114
|
-
import * as os3 from "os";
|
|
5115
|
-
import * as path19 from "path";
|
|
5116
|
-
function getPluginsCatalogRoot() {
|
|
5117
|
-
const here = path19.dirname(new URL(import.meta.url).pathname);
|
|
5118
|
-
const candidates = [
|
|
5119
|
-
path19.join(here, "..", "plugins"),
|
|
5120
|
-
// dev: src/scripts → src/plugins
|
|
5121
|
-
path19.join(here, "..", "..", "plugins"),
|
|
5122
|
-
// built: dist/scripts → dist/plugins
|
|
5123
|
-
path19.join(here, "..", "..", "src", "plugins")
|
|
5124
|
-
// fallback
|
|
5125
|
-
];
|
|
5126
|
-
for (const c of candidates) {
|
|
5127
|
-
if (fs20.existsSync(c) && fs20.statSync(c).isDirectory()) return c;
|
|
5128
|
-
}
|
|
5129
|
-
return candidates[0];
|
|
5130
|
-
}
|
|
5131
|
-
function copyDir(src, dst) {
|
|
5132
|
-
fs20.mkdirSync(dst, { recursive: true });
|
|
5133
|
-
for (const ent of fs20.readdirSync(src, { withFileTypes: true })) {
|
|
5134
|
-
const s = path19.join(src, ent.name);
|
|
5135
|
-
const d = path19.join(dst, ent.name);
|
|
5136
|
-
if (ent.isDirectory()) copyDir(s, d);
|
|
5137
|
-
else if (ent.isFile()) fs20.copyFileSync(s, d);
|
|
5138
|
-
}
|
|
5139
|
-
}
|
|
5140
|
-
var buildSyntheticPlugin;
|
|
5141
|
-
var init_buildSyntheticPlugin = __esm({
|
|
5142
|
-
"src/scripts/buildSyntheticPlugin.ts"() {
|
|
5143
|
-
"use strict";
|
|
5144
|
-
buildSyntheticPlugin = async (ctx, profile) => {
|
|
5145
|
-
const cc = profile.claudeCode;
|
|
5146
|
-
const needsSynthetic = cc.skills.length > 0 || cc.commands.length > 0 || cc.hooks.length > 0;
|
|
5147
|
-
if (!needsSynthetic) return;
|
|
5148
|
-
const catalog = getPluginsCatalogRoot();
|
|
5149
|
-
const runId = `${profile.name}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
5150
|
-
const root = path19.join(os3.tmpdir(), `kody-synth-${runId}`);
|
|
5151
|
-
fs20.mkdirSync(path19.join(root, ".claude-plugin"), { recursive: true });
|
|
5152
|
-
const resolvePart = (bucket, entry) => {
|
|
5153
|
-
const local = path19.join(profile.dir, bucket, entry);
|
|
5154
|
-
if (fs20.existsSync(local)) return local;
|
|
5155
|
-
const shared = path19.resolve(profile.dir, "..", "..", "shared", bucket, entry);
|
|
5156
|
-
if (fs20.existsSync(shared)) return shared;
|
|
5157
|
-
const central = path19.join(catalog, bucket, entry);
|
|
5158
|
-
if (fs20.existsSync(central)) return central;
|
|
5159
|
-
throw new Error(
|
|
5160
|
-
`buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${path19.dirname(shared)}/), or catalog (${catalog}/${bucket}/)`
|
|
5161
|
-
);
|
|
5162
|
-
};
|
|
5163
|
-
if (cc.skills.length > 0) {
|
|
5164
|
-
const dst = path19.join(root, "skills");
|
|
5165
|
-
fs20.mkdirSync(dst, { recursive: true });
|
|
5166
|
-
for (const name of cc.skills) {
|
|
5167
|
-
copyDir(resolvePart("skills", name), path19.join(dst, name));
|
|
5168
|
-
}
|
|
5169
|
-
}
|
|
5170
|
-
if (cc.commands.length > 0) {
|
|
5171
|
-
const dst = path19.join(root, "commands");
|
|
5172
|
-
fs20.mkdirSync(dst, { recursive: true });
|
|
5173
|
-
for (const name of cc.commands) {
|
|
5174
|
-
fs20.copyFileSync(resolvePart("commands", `${name}.md`), path19.join(dst, `${name}.md`));
|
|
5175
|
-
}
|
|
5176
|
-
}
|
|
5177
|
-
if (cc.hooks.length > 0) {
|
|
5178
|
-
const dst = path19.join(root, "hooks");
|
|
5179
|
-
fs20.mkdirSync(dst, { recursive: true });
|
|
5180
|
-
const merged = { hooks: {} };
|
|
5181
|
-
for (const name of cc.hooks) {
|
|
5182
|
-
const src = resolvePart("hooks", `${name}.json`);
|
|
5183
|
-
const parsed = JSON.parse(fs20.readFileSync(src, "utf-8"));
|
|
5184
|
-
for (const [event, entries] of Object.entries(parsed.hooks ?? {})) {
|
|
5185
|
-
if (!Array.isArray(entries)) continue;
|
|
5186
|
-
if (!merged.hooks[event]) merged.hooks[event] = [];
|
|
5187
|
-
merged.hooks[event].push(...entries);
|
|
5188
|
-
}
|
|
5189
|
-
}
|
|
5190
|
-
fs20.writeFileSync(path19.join(dst, "hooks.json"), `${JSON.stringify(merged, null, 2)}
|
|
5191
|
-
`);
|
|
5192
|
-
}
|
|
5193
|
-
const manifest = {
|
|
5194
|
-
name: `kody-synth-${profile.name}`,
|
|
5195
|
-
version: "1.0.0",
|
|
5196
|
-
description: `Synthetic plugin assembled by Kody for profile '${profile.name}' at runtime.`
|
|
5197
|
-
};
|
|
5198
|
-
if (cc.skills.length > 0) manifest.skills = ["./skills/"];
|
|
5199
|
-
if (cc.commands.length > 0) manifest.commands = ["./commands/"];
|
|
5200
|
-
fs20.writeFileSync(path19.join(root, ".claude-plugin", "plugin.json"), `${JSON.stringify(manifest, null, 2)}
|
|
5201
|
-
`);
|
|
5202
|
-
ctx.data.syntheticPluginPath = root;
|
|
5203
|
-
};
|
|
5204
|
-
}
|
|
5205
|
-
});
|
|
5206
|
-
|
|
5207
|
-
// src/subagents.ts
|
|
5208
|
-
import * as fs21 from "fs";
|
|
5209
|
-
import * as path20 from "path";
|
|
5210
|
-
function splitFrontmatter(raw) {
|
|
5211
|
-
const match = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(raw);
|
|
5212
|
-
if (!match) return { fm: {}, body: raw.trim() };
|
|
5213
|
-
const fm = {};
|
|
5214
|
-
for (const line of match[1].split("\n")) {
|
|
5215
|
-
const idx = line.indexOf(":");
|
|
5216
|
-
if (idx === -1) continue;
|
|
5217
|
-
fm[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
|
|
5218
|
-
}
|
|
5219
|
-
return { fm, body: (match[2] ?? "").trim() };
|
|
5220
|
-
}
|
|
5221
|
-
function resolveAgentFile2(profileDir, name) {
|
|
5222
|
-
const local = path20.join(profileDir, "agents", `${name}.md`);
|
|
5223
|
-
if (fs21.existsSync(local)) return local;
|
|
5224
|
-
const shared = path20.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
|
|
5225
|
-
if (fs21.existsSync(shared)) return shared;
|
|
5226
|
-
const central = path20.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
|
|
5227
|
-
if (fs21.existsSync(central)) return central;
|
|
5228
|
-
throw new Error(
|
|
5229
|
-
`loadSubagents: agent '${name}' not found in ${profileDir}/agents/, hydrated shared assets, or engine catalog`
|
|
5230
|
-
);
|
|
5231
|
-
}
|
|
5232
|
-
function captureSubagentTemplates(profile) {
|
|
5233
|
-
const names = profile.claudeCode.subagents;
|
|
5234
|
-
if (!names || names.length === 0) return {};
|
|
5235
|
-
const out = {};
|
|
5236
|
-
for (const name of names) {
|
|
5237
|
-
try {
|
|
5238
|
-
out[name] = fs21.readFileSync(resolveAgentFile2(profile.dir, name), "utf-8");
|
|
5239
|
-
} catch {
|
|
5240
|
-
}
|
|
5241
|
-
}
|
|
5242
|
-
return out;
|
|
5243
|
-
}
|
|
5244
|
-
function loadSubagents(profile) {
|
|
5245
|
-
const names = profile.claudeCode.subagents;
|
|
5246
|
-
if (!names || names.length === 0) return void 0;
|
|
5247
|
-
const agents = {};
|
|
5248
|
-
for (const name of names) {
|
|
5249
|
-
const raw = profile.subagentTemplates?.[name] ?? fs21.readFileSync(resolveAgentFile2(profile.dir, name), "utf-8");
|
|
5250
|
-
const { fm, body } = splitFrontmatter(raw);
|
|
5251
|
-
if (!body) throw new Error(`loadSubagents: agent '${name}' has an empty prompt body`);
|
|
5252
|
-
const def = {
|
|
5253
|
-
description: fm.description ?? `Subagent ${name}`,
|
|
5254
|
-
prompt: body
|
|
5255
|
-
};
|
|
5256
|
-
if (fm.tools) {
|
|
5257
|
-
const tools = fm.tools.split(",").map((t) => t.trim()).filter(Boolean);
|
|
5258
|
-
if (tools.length > 0) def.tools = tools;
|
|
5259
|
-
}
|
|
5260
|
-
if (fm.model) def.model = fm.model;
|
|
5261
|
-
agents[fm.name || name] = def;
|
|
5262
|
-
}
|
|
5263
|
-
return agents;
|
|
5264
|
-
}
|
|
5265
|
-
var init_subagents = __esm({
|
|
5266
|
-
"src/subagents.ts"() {
|
|
5267
|
-
"use strict";
|
|
5268
|
-
init_buildSyntheticPlugin();
|
|
5269
|
-
}
|
|
5270
|
-
});
|
|
5271
|
-
|
|
5272
5294
|
// src/profile.ts
|
|
5273
5295
|
import { createHash as createHash3 } from "crypto";
|
|
5274
5296
|
import * as fs22 from "fs";
|
|
@@ -15014,7 +15036,7 @@ var init_loadAgentAdhoc = __esm({
|
|
|
15014
15036
|
if (!agentSlug) {
|
|
15015
15037
|
throw new Error("loadAgentAdhoc: ctx.args.agent must be a non-empty slug");
|
|
15016
15038
|
}
|
|
15017
|
-
const agentPath =
|
|
15039
|
+
const agentPath = resolveAgentFile2(ctx.cwd, agentSlug, agentsDir);
|
|
15018
15040
|
if (!fs39.existsSync(agentPath)) {
|
|
15019
15041
|
throw new Error(`loadAgentAdhoc: agent identity not found: ${agentPath}`);
|
|
15020
15042
|
}
|
|
@@ -15439,7 +15461,7 @@ var init_loadJobFromFile = __esm({
|
|
|
15439
15461
|
let agentTitle = "";
|
|
15440
15462
|
let agentIdentity = "";
|
|
15441
15463
|
if (agentSlug) {
|
|
15442
|
-
const agentPath =
|
|
15464
|
+
const agentPath = resolveAgentFile2(ctx.cwd, agentSlug, agentsDir);
|
|
15443
15465
|
if (!fs40.existsSync(agentPath)) {
|
|
15444
15466
|
throw new Error(
|
|
15445
15467
|
`loadJobFromFile: capability '${slug}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
@@ -22991,13 +23013,13 @@ init_agents();
|
|
|
22991
23013
|
init_config();
|
|
22992
23014
|
init_registry();
|
|
22993
23015
|
init_task_artifacts();
|
|
22994
|
-
import * as
|
|
22995
|
-
import * as
|
|
23016
|
+
import * as fs16 from "fs";
|
|
23017
|
+
import * as path17 from "path";
|
|
22996
23018
|
|
|
22997
23019
|
// src/chat/attachments.ts
|
|
22998
23020
|
init_runtimePaths();
|
|
22999
|
-
import * as
|
|
23000
|
-
import * as
|
|
23021
|
+
import * as fs13 from "fs";
|
|
23022
|
+
import * as path14 from "path";
|
|
23001
23023
|
var INLINE_ATTACHMENT_RE = /(?:\[(?:Image|File): ([^\]]*)\]\n)?data:([\w.+-]+\/[\w.+-]+);base64,([A-Za-z0-9+/=]+)/g;
|
|
23002
23024
|
var EXT_BY_MIME = {
|
|
23003
23025
|
"image/png": "png",
|
|
@@ -23030,11 +23052,11 @@ function prepareAttachments(turns, cwd, sessionId) {
|
|
|
23030
23052
|
if (!isImage) return `[File: ${name}]`;
|
|
23031
23053
|
try {
|
|
23032
23054
|
if (!dirEnsured) {
|
|
23033
|
-
|
|
23055
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
23034
23056
|
dirEnsured = true;
|
|
23035
23057
|
}
|
|
23036
|
-
const filePath =
|
|
23037
|
-
|
|
23058
|
+
const filePath = path14.join(dir, `${imageCounter}.${extFor(mime)}`);
|
|
23059
|
+
fs13.writeFileSync(filePath, Buffer.from(data, "base64"));
|
|
23038
23060
|
imageCounter += 1;
|
|
23039
23061
|
imagePaths.push(filePath);
|
|
23040
23062
|
return `[Image "${name}" is attached \u2014 saved to ${filePath}. Use the Read tool on that exact path to view it.]`;
|
|
@@ -23051,8 +23073,8 @@ function prepareAttachments(turns, cwd, sessionId) {
|
|
|
23051
23073
|
|
|
23052
23074
|
// src/chat/codex-app-server.ts
|
|
23053
23075
|
import { spawn as spawn3 } from "child_process";
|
|
23054
|
-
import * as
|
|
23055
|
-
import * as
|
|
23076
|
+
import * as fs14 from "fs";
|
|
23077
|
+
import * as path15 from "path";
|
|
23056
23078
|
import { createInterface } from "readline";
|
|
23057
23079
|
function codexThreadStartParams(args) {
|
|
23058
23080
|
return {
|
|
@@ -23223,11 +23245,11 @@ var CodexAppServerClient = class {
|
|
|
23223
23245
|
};
|
|
23224
23246
|
var clients = /* @__PURE__ */ new Map();
|
|
23225
23247
|
function threadMapPath(cwd) {
|
|
23226
|
-
return
|
|
23248
|
+
return path15.join(cwd, ".kody-engine", "runtime", "codex-threads.json");
|
|
23227
23249
|
}
|
|
23228
23250
|
function readThreadMap(cwd) {
|
|
23229
23251
|
try {
|
|
23230
|
-
const value = JSON.parse(
|
|
23252
|
+
const value = JSON.parse(fs14.readFileSync(threadMapPath(cwd), "utf8"));
|
|
23231
23253
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
23232
23254
|
return Object.fromEntries(
|
|
23233
23255
|
Object.entries(value).filter(
|
|
@@ -23240,8 +23262,8 @@ function readThreadMap(cwd) {
|
|
|
23240
23262
|
}
|
|
23241
23263
|
function writeThreadMap(cwd, map) {
|
|
23242
23264
|
const file = threadMapPath(cwd);
|
|
23243
|
-
|
|
23244
|
-
|
|
23265
|
+
fs14.mkdirSync(path15.dirname(file), { recursive: true });
|
|
23266
|
+
fs14.writeFileSync(file, `${JSON.stringify(map, null, 2)}
|
|
23245
23267
|
`);
|
|
23246
23268
|
}
|
|
23247
23269
|
async function runCodexChatTurn(args) {
|
|
@@ -23331,8 +23353,8 @@ async function runCodexChatTurn(args) {
|
|
|
23331
23353
|
}
|
|
23332
23354
|
|
|
23333
23355
|
// src/chat/events.ts
|
|
23334
|
-
import * as
|
|
23335
|
-
import * as
|
|
23356
|
+
import * as fs15 from "fs";
|
|
23357
|
+
import * as path16 from "path";
|
|
23336
23358
|
import posixPath2 from "path/posix";
|
|
23337
23359
|
var BackendEventSink = class {
|
|
23338
23360
|
constructor(append, tenantId2, sessionId) {
|
|
@@ -23348,7 +23370,7 @@ var BackendEventSink = class {
|
|
|
23348
23370
|
}
|
|
23349
23371
|
};
|
|
23350
23372
|
function eventsFilePath(cwd, sessionId) {
|
|
23351
|
-
return
|
|
23373
|
+
return path16.join(cwd, ".kody-engine", "runtime", "events", `${sessionId}.jsonl`);
|
|
23352
23374
|
}
|
|
23353
23375
|
var FileSink = class {
|
|
23354
23376
|
constructor(file) {
|
|
@@ -23356,8 +23378,8 @@ var FileSink = class {
|
|
|
23356
23378
|
}
|
|
23357
23379
|
file;
|
|
23358
23380
|
async emit(event) {
|
|
23359
|
-
|
|
23360
|
-
|
|
23381
|
+
fs15.mkdirSync(path16.dirname(this.file), { recursive: true });
|
|
23382
|
+
fs15.appendFileSync(this.file, `${JSON.stringify(event)}
|
|
23361
23383
|
`);
|
|
23362
23384
|
}
|
|
23363
23385
|
};
|
|
@@ -23600,7 +23622,7 @@ function buildImplementationCatalog() {
|
|
|
23600
23622
|
const entries = [];
|
|
23601
23623
|
for (const { name, profilePath } of discovered) {
|
|
23602
23624
|
try {
|
|
23603
|
-
const raw = JSON.parse(
|
|
23625
|
+
const raw = JSON.parse(fs16.readFileSync(profilePath, "utf-8"));
|
|
23604
23626
|
const describe = typeof raw.describe === "string" ? raw.describe : "";
|
|
23605
23627
|
const firstSentence = describe.split(/(?<=[.!?])\s+/, 1)[0] ?? "";
|
|
23606
23628
|
entries.push({ name, describe: firstSentence.trim() });
|
|
@@ -23708,7 +23730,7 @@ async function runChatTurn(opts) {
|
|
|
23708
23730
|
quiet: opts.quiet,
|
|
23709
23731
|
additionalDirectories: [
|
|
23710
23732
|
taskArtifactsPaths.absDir,
|
|
23711
|
-
...Array.from(new Set(imagePaths.map((p2) =>
|
|
23733
|
+
...Array.from(new Set(imagePaths.map((p2) => path17.dirname(p2))))
|
|
23712
23734
|
],
|
|
23713
23735
|
systemPromptAppend: systemPrompt,
|
|
23714
23736
|
...opts.reasoningEffort ? { reasoningEffort: opts.reasoningEffort } : {},
|
|
@@ -23892,10 +23914,10 @@ async function emit(sink, type, sessionId, suffix, payload) {
|
|
|
23892
23914
|
var MEMORY_INDEX_REL = ".kody-engine/runtime/memory/INDEX.md";
|
|
23893
23915
|
var MAX_INDEX_BYTES = 8e3;
|
|
23894
23916
|
function readMemoryIndexBlock(cwd) {
|
|
23895
|
-
const indexPath =
|
|
23917
|
+
const indexPath = path17.join(cwd, MEMORY_INDEX_REL);
|
|
23896
23918
|
let raw;
|
|
23897
23919
|
try {
|
|
23898
|
-
raw =
|
|
23920
|
+
raw = fs16.readFileSync(indexPath, "utf-8");
|
|
23899
23921
|
} catch {
|
|
23900
23922
|
return "";
|
|
23901
23923
|
}
|
|
@@ -23915,17 +23937,17 @@ _\u2026 (memory index truncated; use recall_search to read more)_` : trimmed;
|
|
|
23915
23937
|
var CONTEXT_DIR_REL = ".kody-engine/runtime/context";
|
|
23916
23938
|
var MAX_CONTEXT_BYTES = 12e3;
|
|
23917
23939
|
function readContextBlock(cwd) {
|
|
23918
|
-
const dir =
|
|
23940
|
+
const dir = path17.join(cwd, CONTEXT_DIR_REL);
|
|
23919
23941
|
let files;
|
|
23920
23942
|
try {
|
|
23921
|
-
files =
|
|
23943
|
+
files = fs16.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
23922
23944
|
} catch {
|
|
23923
23945
|
return "";
|
|
23924
23946
|
}
|
|
23925
23947
|
const sections = [];
|
|
23926
23948
|
for (const file of files) {
|
|
23927
23949
|
try {
|
|
23928
|
-
const content =
|
|
23950
|
+
const content = fs16.readFileSync(path17.join(dir, file), "utf-8").trim();
|
|
23929
23951
|
if (content) sections.push(`### ${file.replace(/\.md$/, "")}
|
|
23930
23952
|
|
|
23931
23953
|
${content}`);
|
|
@@ -23951,7 +23973,7 @@ var SYSTEM_PROMPT_OVERRIDE_REL = ".kody-engine/runtime/system-prompt.md";
|
|
|
23951
23973
|
function readSystemPromptOverride(cwd) {
|
|
23952
23974
|
let raw;
|
|
23953
23975
|
try {
|
|
23954
|
-
raw =
|
|
23976
|
+
raw = fs16.readFileSync(path17.join(cwd, SYSTEM_PROMPT_OVERRIDE_REL), "utf-8");
|
|
23955
23977
|
} catch {
|
|
23956
23978
|
return null;
|
|
23957
23979
|
}
|
|
@@ -23959,10 +23981,10 @@ function readSystemPromptOverride(cwd) {
|
|
|
23959
23981
|
return trimmed.length > 0 ? trimmed : null;
|
|
23960
23982
|
}
|
|
23961
23983
|
function readInstructionsBlock(cwd) {
|
|
23962
|
-
const instructionsPath =
|
|
23984
|
+
const instructionsPath = path17.join(cwd, INSTRUCTIONS_REL);
|
|
23963
23985
|
let raw;
|
|
23964
23986
|
try {
|
|
23965
|
-
raw =
|
|
23987
|
+
raw = fs16.readFileSync(instructionsPath, "utf-8");
|
|
23966
23988
|
} catch {
|
|
23967
23989
|
return "";
|
|
23968
23990
|
}
|
|
@@ -23996,15 +24018,15 @@ function resolveBrainDriver(runtime) {
|
|
|
23996
24018
|
}
|
|
23997
24019
|
|
|
23998
24020
|
// src/chat/session.ts
|
|
23999
|
-
import * as
|
|
24000
|
-
import * as
|
|
24021
|
+
import * as fs17 from "fs";
|
|
24022
|
+
import * as path18 from "path";
|
|
24001
24023
|
import posixPath3 from "path/posix";
|
|
24002
24024
|
function sessionFilePath(cwd, sessionId) {
|
|
24003
|
-
return
|
|
24025
|
+
return path18.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
|
|
24004
24026
|
}
|
|
24005
24027
|
function readSession(file) {
|
|
24006
|
-
if (!
|
|
24007
|
-
const raw =
|
|
24028
|
+
if (!fs17.existsSync(file)) return [];
|
|
24029
|
+
const raw = fs17.readFileSync(file, "utf-8").trim();
|
|
24008
24030
|
if (!raw) return [];
|
|
24009
24031
|
const turns = [];
|
|
24010
24032
|
for (const line of raw.split("\n")) {
|
|
@@ -24027,8 +24049,8 @@ init_config();
|
|
|
24027
24049
|
init_state_backend();
|
|
24028
24050
|
init_workflowDefinitions();
|
|
24029
24051
|
import { createHash as createHash2 } from "crypto";
|
|
24030
|
-
import * as
|
|
24031
|
-
import * as
|
|
24052
|
+
import * as fs19 from "fs";
|
|
24053
|
+
import * as path20 from "path";
|
|
24032
24054
|
var SLUG_RE = /^[a-z0-9][a-z0-9_-]{0,127}$/;
|
|
24033
24055
|
var REPOSITORY_OWNED_NAMESPACES = ["loops"];
|
|
24034
24056
|
function assertSafeDefinitionPath(filePath) {
|
|
@@ -24060,9 +24082,9 @@ function verifyDefinition(definition) {
|
|
|
24060
24082
|
}
|
|
24061
24083
|
function writeBundle(root, bundle) {
|
|
24062
24084
|
for (const [filePath, contents] of Object.entries(bundle.files)) {
|
|
24063
|
-
const target =
|
|
24064
|
-
|
|
24065
|
-
|
|
24085
|
+
const target = path20.join(root, filePath);
|
|
24086
|
+
fs19.mkdirSync(path20.dirname(target), { recursive: true });
|
|
24087
|
+
fs19.writeFileSync(target, contents, "utf8");
|
|
24066
24088
|
}
|
|
24067
24089
|
}
|
|
24068
24090
|
function writeDefinition(root, kind, definition) {
|
|
@@ -24070,22 +24092,22 @@ function writeDefinition(root, kind, definition) {
|
|
|
24070
24092
|
if (kind === "agent") {
|
|
24071
24093
|
const raw = bundle.files["agent.md"];
|
|
24072
24094
|
if (typeof raw !== "string") throw new Error(`agent definition ${definition.slug} is missing agent.md`);
|
|
24073
|
-
|
|
24095
|
+
fs19.writeFileSync(path20.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
|
|
24074
24096
|
return;
|
|
24075
24097
|
}
|
|
24076
24098
|
if (kind === "goal") {
|
|
24077
|
-
writeBundle(
|
|
24099
|
+
writeBundle(path20.join(root, "goals", definition.slug), bundle);
|
|
24078
24100
|
return;
|
|
24079
24101
|
}
|
|
24080
24102
|
if (kind === "implementation") {
|
|
24081
|
-
writeBundle(
|
|
24103
|
+
writeBundle(path20.join(root, "implementations", definition.slug), bundle);
|
|
24082
24104
|
return;
|
|
24083
24105
|
}
|
|
24084
24106
|
if (kind === "asset") {
|
|
24085
|
-
writeBundle(
|
|
24107
|
+
writeBundle(path20.join(root, "shared"), bundle);
|
|
24086
24108
|
return;
|
|
24087
24109
|
}
|
|
24088
|
-
writeBundle(
|
|
24110
|
+
writeBundle(path20.join(root, "capabilities", definition.slug), bundle);
|
|
24089
24111
|
}
|
|
24090
24112
|
function writeWorkflow(root, document) {
|
|
24091
24113
|
const workflow = normalizeWorkflowDefinition(document.definition);
|
|
@@ -24093,28 +24115,28 @@ function writeWorkflow(root, document) {
|
|
|
24093
24115
|
const contents = `${JSON.stringify(workflow, null, 2)}
|
|
24094
24116
|
`;
|
|
24095
24117
|
const bundle = { schemaVersion: 1, files: { "workflow.json": contents } };
|
|
24096
|
-
const target =
|
|
24097
|
-
|
|
24098
|
-
|
|
24118
|
+
const target = path20.join(root, workflowDefinitionPath(document.workflowId));
|
|
24119
|
+
fs19.mkdirSync(path20.dirname(target), { recursive: true });
|
|
24120
|
+
fs19.writeFileSync(target, contents, "utf8");
|
|
24099
24121
|
return definitionVersion(bundle);
|
|
24100
24122
|
}
|
|
24101
24123
|
function preserveRepositoryDefinitions(root, staging) {
|
|
24102
24124
|
for (const namespace of REPOSITORY_OWNED_NAMESPACES) {
|
|
24103
|
-
const source =
|
|
24104
|
-
if (!
|
|
24105
|
-
|
|
24125
|
+
const source = path20.join(root, namespace);
|
|
24126
|
+
if (!fs19.existsSync(source)) continue;
|
|
24127
|
+
fs19.cpSync(source, path20.join(staging, namespace), { recursive: true });
|
|
24106
24128
|
}
|
|
24107
24129
|
}
|
|
24108
24130
|
async function hydrateDefinitions(options) {
|
|
24109
|
-
const root =
|
|
24131
|
+
const root = path20.join(options.cwd, ".kody-engine", "definitions");
|
|
24110
24132
|
const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
|
|
24111
|
-
|
|
24112
|
-
|
|
24113
|
-
|
|
24114
|
-
|
|
24115
|
-
|
|
24116
|
-
|
|
24117
|
-
|
|
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 });
|
|
24118
24140
|
try {
|
|
24119
24141
|
const [capabilities, agents, goals, implementations, assets, workflows] = await Promise.all([
|
|
24120
24142
|
options.backend.listDefinitions(options.tenantId, "capability"),
|
|
@@ -24155,13 +24177,13 @@ async function hydrateDefinitions(options) {
|
|
|
24155
24177
|
hydratedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24156
24178
|
versions: Object.fromEntries(Object.entries(versions).sort(([left], [right]) => left.localeCompare(right)))
|
|
24157
24179
|
};
|
|
24158
|
-
|
|
24180
|
+
fs19.writeFileSync(path20.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
24159
24181
|
`, "utf8");
|
|
24160
|
-
|
|
24161
|
-
|
|
24182
|
+
fs19.rmSync(root, { recursive: true, force: true });
|
|
24183
|
+
fs19.renameSync(staging, root);
|
|
24162
24184
|
return { root, tenantId: options.tenantId, versions: manifest.versions };
|
|
24163
24185
|
} catch (error) {
|
|
24164
|
-
|
|
24186
|
+
fs19.rmSync(staging, { recursive: true, force: true });
|
|
24165
24187
|
throw error;
|
|
24166
24188
|
}
|
|
24167
24189
|
}
|
|
@@ -24313,7 +24335,7 @@ init_definition_paths();
|
|
|
24313
24335
|
|
|
24314
24336
|
// src/dispatch.ts
|
|
24315
24337
|
init_config();
|
|
24316
|
-
import * as
|
|
24338
|
+
import * as fs20 from "fs";
|
|
24317
24339
|
|
|
24318
24340
|
// src/cron-match.ts
|
|
24319
24341
|
var FIELD_BOUNDS = [
|
|
@@ -24420,10 +24442,10 @@ function autoDispatch(opts) {
|
|
|
24420
24442
|
}
|
|
24421
24443
|
const eventName = process.env.GITHUB_EVENT_NAME;
|
|
24422
24444
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
24423
|
-
if (!eventName || !eventPath || !
|
|
24445
|
+
if (!eventName || !eventPath || !fs20.existsSync(eventPath)) return null;
|
|
24424
24446
|
let event = {};
|
|
24425
24447
|
try {
|
|
24426
|
-
event = JSON.parse(
|
|
24448
|
+
event = JSON.parse(fs20.readFileSync(eventPath, "utf-8"));
|
|
24427
24449
|
} catch {
|
|
24428
24450
|
return null;
|
|
24429
24451
|
}
|
|
@@ -24547,7 +24569,7 @@ function autoDispatchTyped(opts) {
|
|
|
24547
24569
|
if (legacy) return { kind: "route", ...legacy };
|
|
24548
24570
|
const eventName = process.env.GITHUB_EVENT_NAME;
|
|
24549
24571
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
24550
|
-
if (!eventName || !eventPath || !
|
|
24572
|
+
if (!eventName || !eventPath || !fs20.existsSync(eventPath)) {
|
|
24551
24573
|
return { kind: "silent", reason: "no GHA event context" };
|
|
24552
24574
|
}
|
|
24553
24575
|
if (eventName !== "issue_comment") {
|
|
@@ -24555,7 +24577,7 @@ function autoDispatchTyped(opts) {
|
|
|
24555
24577
|
}
|
|
24556
24578
|
let event = {};
|
|
24557
24579
|
try {
|
|
24558
|
-
event = JSON.parse(
|
|
24580
|
+
event = JSON.parse(fs20.readFileSync(eventPath, "utf-8"));
|
|
24559
24581
|
} catch {
|
|
24560
24582
|
return { kind: "silent", reason: "GHA event payload unreadable" };
|
|
24561
24583
|
}
|
|
@@ -24609,7 +24631,7 @@ function dispatchScheduledWatches(opts) {
|
|
|
24609
24631
|
for (const exe of listRuntimeProfilesForCwd(opts?.cwd ?? process.cwd())) {
|
|
24610
24632
|
let raw;
|
|
24611
24633
|
try {
|
|
24612
|
-
raw =
|
|
24634
|
+
raw = fs20.readFileSync(exe.profilePath, "utf-8");
|
|
24613
24635
|
} catch {
|
|
24614
24636
|
continue;
|
|
24615
24637
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.508",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|