@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 +380 -349
- package/dist/runtime-services/goal-scheduler/scheduler.sh +0 -0
- package/package.json +25 -26
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",
|
|
@@ -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
|
|
703
|
-
import * as
|
|
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
|
-
|
|
737
|
-
|
|
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 (!
|
|
745
|
-
const lines =
|
|
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 (!
|
|
760
|
-
return
|
|
941
|
+
if (!fs5.existsSync(runsDir)) return [];
|
|
942
|
+
return fs5.readdirSync(runsDir).filter((name) => {
|
|
761
943
|
try {
|
|
762
|
-
return
|
|
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
|
|
1685
|
-
import * as
|
|
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 (!
|
|
1882
|
+
if (!fs6.existsSync(absDir)) return [];
|
|
1701
1883
|
let entries;
|
|
1702
1884
|
try {
|
|
1703
|
-
entries =
|
|
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(
|
|
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 (!
|
|
1711
|
-
const entries =
|
|
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 =
|
|
1718
|
-
const bodyPath =
|
|
1719
|
-
const contractPath =
|
|
1720
|
-
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;
|
|
1721
1903
|
if (!isCapabilityFolder(dir)) return null;
|
|
1722
1904
|
try {
|
|
1723
|
-
const rawBody =
|
|
1724
|
-
const contract =
|
|
1725
|
-
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"))) {
|
|
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 =
|
|
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
|
|
1956
|
-
import * as
|
|
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 &&
|
|
1961
|
-
return storeCatalogRoot(
|
|
2142
|
+
if (override && overrideCwd && path8.resolve(cwd) === path8.resolve(overrideCwd)) {
|
|
2143
|
+
return storeCatalogRoot(path8.resolve(override));
|
|
1962
2144
|
}
|
|
1963
|
-
const hydrated =
|
|
1964
|
-
if (
|
|
1965
|
-
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;
|
|
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 &&
|
|
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") ??
|
|
2155
|
+
return storeAssetRoot(cwd, "capabilities") ?? path8.join(definitionsRoot(cwd), "capabilities");
|
|
1974
2156
|
}
|
|
1975
2157
|
function implementationsRoot(cwd = process.cwd()) {
|
|
1976
|
-
return
|
|
2158
|
+
return path8.join(definitionsRoot(cwd), "implementations");
|
|
1977
2159
|
}
|
|
1978
2160
|
function agentsRoot(cwd = process.cwd()) {
|
|
1979
|
-
return storeAssetRoot(cwd, "agent") ??
|
|
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) =>
|
|
1984
|
-
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;
|
|
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 &&
|
|
1991
|
-
const root =
|
|
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() ?
|
|
2175
|
+
return typeof configured === "string" && configured.trim() ? path8.join(root, configured) : null;
|
|
1994
2176
|
}
|
|
1995
2177
|
function readStoreManifest(root) {
|
|
1996
|
-
const file =
|
|
1997
|
-
if (!
|
|
2178
|
+
const file = path8.join(root, "kody-store.json");
|
|
2179
|
+
if (!fs7.existsSync(file)) return null;
|
|
1998
2180
|
try {
|
|
1999
|
-
return JSON.parse(
|
|
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
|
|
2012
|
-
import * as
|
|
2193
|
+
import * as fs8 from "fs";
|
|
2194
|
+
import * as path9 from "path";
|
|
2013
2195
|
function getImplementationsRoot() {
|
|
2014
|
-
const here =
|
|
2196
|
+
const here = path9.dirname(new URL(import.meta.url).pathname);
|
|
2015
2197
|
const candidates = [
|
|
2016
|
-
|
|
2198
|
+
path9.join(here, "implementations"),
|
|
2017
2199
|
// dev: src/
|
|
2018
|
-
|
|
2200
|
+
path9.join(here, "..", "implementations"),
|
|
2019
2201
|
// built: dist/bin → dist/implementations
|
|
2020
|
-
|
|
2202
|
+
path9.join(here, "..", "src", "implementations")
|
|
2021
2203
|
// fallback
|
|
2022
2204
|
];
|
|
2023
2205
|
for (const c of candidates) {
|
|
2024
|
-
if (
|
|
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 =
|
|
2211
|
+
const here = path9.dirname(new URL(import.meta.url).pathname);
|
|
2030
2212
|
const candidates = [
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
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 (
|
|
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 =
|
|
2226
|
+
const here = path9.dirname(new URL(import.meta.url).pathname);
|
|
2045
2227
|
const candidates = [
|
|
2046
|
-
|
|
2228
|
+
path9.join(here, "capabilities"),
|
|
2047
2229
|
// dev: src/
|
|
2048
|
-
|
|
2230
|
+
path9.join(here, "..", "capabilities"),
|
|
2049
2231
|
// built: dist/bin → dist/capabilities
|
|
2050
|
-
|
|
2232
|
+
path9.join(here, "..", "src", "capabilities")
|
|
2051
2233
|
// fallback
|
|
2052
2234
|
];
|
|
2053
2235
|
for (const c of candidates) {
|
|
2054
|
-
if (
|
|
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 (!
|
|
2259
|
+
if (!fs8.existsSync(root)) continue;
|
|
2078
2260
|
const requireImplementationProfile = isCapabilityRoot(root);
|
|
2079
|
-
const entries =
|
|
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 (
|
|
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 (
|
|
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(
|
|
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 =
|
|
2190
|
-
if (
|
|
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 &&
|
|
2374
|
+
return knownRoots.some((candidate) => candidate && path9.normalize(candidate) === normalized);
|
|
2193
2375
|
}
|
|
2194
2376
|
function implementationRuntimePath(root, name) {
|
|
2195
|
-
const runtimePath =
|
|
2196
|
-
if (
|
|
2197
|
-
const internalProfilePath =
|
|
2198
|
-
if (
|
|
2199
|
-
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);
|
|
2200
2382
|
}
|
|
2201
2383
|
function isImplementationProfile(profilePath, requireImplementationProfile) {
|
|
2202
2384
|
if (!requireImplementationProfile) return true;
|
|
2203
2385
|
try {
|
|
2204
|
-
const raw = JSON.parse(
|
|
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 (!
|
|
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 (!
|
|
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(
|
|
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
|
|
3307
|
-
import * as
|
|
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 =
|
|
3323
|
-
const dir =
|
|
3324
|
-
if (dir !== root && !dir.startsWith(root +
|
|
3325
|
-
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;
|
|
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
|
-
|
|
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
|
|
3452
|
-
import * as
|
|
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
|
-
|
|
3522
|
-
const ndjsonPath =
|
|
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 =
|
|
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
|
|
3915
|
-
import * as
|
|
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 =
|
|
3924
|
-
if (
|
|
3925
|
-
const body = stripFrontmatter(
|
|
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
|
|
3936
|
-
const localPath =
|
|
3937
|
-
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;
|
|
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
|
|
3970
|
-
import
|
|
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
|
-
|
|
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 =
|
|
4007
|
-
if (!
|
|
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 =
|
|
4204
|
+
const full = path13.join(absDir, name);
|
|
4014
4205
|
try {
|
|
4015
|
-
const stat =
|
|
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 =
|
|
4032
|
-
if (!
|
|
4033
|
-
const stat =
|
|
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 =
|
|
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
|
|
4397
|
-
import * as
|
|
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
|
-
|
|
4441
|
-
|
|
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 (!
|
|
4445
|
-
const workflow = parseWorkflowDefinition(
|
|
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:
|
|
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
|
|
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 || !
|
|
4710
|
+
if (!eventPath || !fs21.existsSync(eventPath)) return;
|
|
4520
4711
|
let event = null;
|
|
4521
4712
|
try {
|
|
4522
|
-
event = JSON.parse(
|
|
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 =
|
|
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 =
|
|
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
|
|
22986
|
-
import * as
|
|
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
|
|
22991
|
-
import * as
|
|
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
|
-
|
|
23055
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
23025
23056
|
dirEnsured = true;
|
|
23026
23057
|
}
|
|
23027
|
-
const filePath =
|
|
23028
|
-
|
|
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
|
|
23046
|
-
import * as
|
|
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
|
|
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(
|
|
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
|
-
|
|
23235
|
-
|
|
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
|
|
23326
|
-
import * as
|
|
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
|
|
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
|
-
|
|
23351
|
-
|
|
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(
|
|
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) =>
|
|
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 =
|
|
23917
|
+
const indexPath = path17.join(cwd, MEMORY_INDEX_REL);
|
|
23887
23918
|
let raw;
|
|
23888
23919
|
try {
|
|
23889
|
-
raw =
|
|
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 =
|
|
23940
|
+
const dir = path17.join(cwd, CONTEXT_DIR_REL);
|
|
23910
23941
|
let files;
|
|
23911
23942
|
try {
|
|
23912
|
-
files =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
23984
|
+
const instructionsPath = path17.join(cwd, INSTRUCTIONS_REL);
|
|
23954
23985
|
let raw;
|
|
23955
23986
|
try {
|
|
23956
|
-
raw =
|
|
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
|
|
23991
|
-
import * as
|
|
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
|
|
24025
|
+
return path18.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
|
|
23995
24026
|
}
|
|
23996
24027
|
function readSession(file) {
|
|
23997
|
-
if (!
|
|
23998
|
-
const raw =
|
|
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
|
|
24022
|
-
import * as
|
|
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 =
|
|
24055
|
-
|
|
24056
|
-
|
|
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
|
-
|
|
24095
|
+
fs19.writeFileSync(path20.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
|
|
24065
24096
|
return;
|
|
24066
24097
|
}
|
|
24067
24098
|
if (kind === "goal") {
|
|
24068
|
-
writeBundle(
|
|
24099
|
+
writeBundle(path20.join(root, "goals", definition.slug), bundle);
|
|
24069
24100
|
return;
|
|
24070
24101
|
}
|
|
24071
24102
|
if (kind === "implementation") {
|
|
24072
|
-
writeBundle(
|
|
24103
|
+
writeBundle(path20.join(root, "implementations", definition.slug), bundle);
|
|
24073
24104
|
return;
|
|
24074
24105
|
}
|
|
24075
24106
|
if (kind === "asset") {
|
|
24076
|
-
writeBundle(
|
|
24107
|
+
writeBundle(path20.join(root, "shared"), bundle);
|
|
24077
24108
|
return;
|
|
24078
24109
|
}
|
|
24079
|
-
writeBundle(
|
|
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 =
|
|
24088
|
-
|
|
24089
|
-
|
|
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 =
|
|
24095
|
-
if (!
|
|
24096
|
-
|
|
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 =
|
|
24131
|
+
const root = path20.join(options.cwd, ".kody-engine", "definitions");
|
|
24101
24132
|
const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
|
|
24102
|
-
|
|
24103
|
-
|
|
24104
|
-
|
|
24105
|
-
|
|
24106
|
-
|
|
24107
|
-
|
|
24108
|
-
|
|
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
|
-
|
|
24180
|
+
fs19.writeFileSync(path20.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
24150
24181
|
`, "utf8");
|
|
24151
|
-
|
|
24152
|
-
|
|
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
|
-
|
|
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
|
|
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 || !
|
|
24445
|
+
if (!eventName || !eventPath || !fs20.existsSync(eventPath)) return null;
|
|
24415
24446
|
let event = {};
|
|
24416
24447
|
try {
|
|
24417
|
-
event = JSON.parse(
|
|
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 || !
|
|
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(
|
|
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 =
|
|
24634
|
+
raw = fs20.readFileSync(exe.profilePath, "utf-8");
|
|
24604
24635
|
} catch {
|
|
24605
24636
|
continue;
|
|
24606
24637
|
}
|