@kody-ade/kody-engine 0.4.433 → 0.4.435
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 +505 -477
- package/package.json +2 -2
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.435",
|
|
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",
|
|
@@ -47,7 +47,7 @@ var init_package = __esm({
|
|
|
47
47
|
"lint:fix": "biome check --write",
|
|
48
48
|
format: "biome format --write",
|
|
49
49
|
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
50
|
-
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
50
|
+
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
51
51
|
prepublishOnly: "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm test:runtime-services && pnpm build && pnpm verify:package"
|
|
52
52
|
},
|
|
53
53
|
dependencies: {
|
|
@@ -4194,7 +4194,7 @@ var init_task_artifacts = __esm({
|
|
|
4194
4194
|
|
|
4195
4195
|
// src/gha.ts
|
|
4196
4196
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
4197
|
-
import * as
|
|
4197
|
+
import * as fs18 from "fs";
|
|
4198
4198
|
function getRunUrl() {
|
|
4199
4199
|
const server = process.env.GITHUB_SERVER_URL;
|
|
4200
4200
|
const repo = process.env.GITHUB_REPOSITORY;
|
|
@@ -4205,10 +4205,10 @@ function getRunUrl() {
|
|
|
4205
4205
|
function reactToTriggerComment(cwd) {
|
|
4206
4206
|
if (process.env.GITHUB_EVENT_NAME !== "issue_comment") return;
|
|
4207
4207
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
4208
|
-
if (!eventPath || !
|
|
4208
|
+
if (!eventPath || !fs18.existsSync(eventPath)) return;
|
|
4209
4209
|
let event = null;
|
|
4210
4210
|
try {
|
|
4211
|
-
event = JSON.parse(
|
|
4211
|
+
event = JSON.parse(fs18.readFileSync(eventPath, "utf-8"));
|
|
4212
4212
|
} catch {
|
|
4213
4213
|
return;
|
|
4214
4214
|
}
|
|
@@ -4771,31 +4771,31 @@ var init_lifecycles = __esm({
|
|
|
4771
4771
|
});
|
|
4772
4772
|
|
|
4773
4773
|
// src/scripts/buildSyntheticPlugin.ts
|
|
4774
|
-
import * as
|
|
4774
|
+
import * as fs19 from "fs";
|
|
4775
4775
|
import * as os3 from "os";
|
|
4776
|
-
import * as
|
|
4776
|
+
import * as path18 from "path";
|
|
4777
4777
|
function getPluginsCatalogRoot() {
|
|
4778
|
-
const here =
|
|
4778
|
+
const here = path18.dirname(new URL(import.meta.url).pathname);
|
|
4779
4779
|
const candidates = [
|
|
4780
|
-
|
|
4780
|
+
path18.join(here, "..", "plugins"),
|
|
4781
4781
|
// dev: src/scripts → src/plugins
|
|
4782
|
-
|
|
4782
|
+
path18.join(here, "..", "..", "plugins"),
|
|
4783
4783
|
// built: dist/scripts → dist/plugins
|
|
4784
|
-
|
|
4784
|
+
path18.join(here, "..", "..", "src", "plugins")
|
|
4785
4785
|
// fallback
|
|
4786
4786
|
];
|
|
4787
4787
|
for (const c of candidates) {
|
|
4788
|
-
if (
|
|
4788
|
+
if (fs19.existsSync(c) && fs19.statSync(c).isDirectory()) return c;
|
|
4789
4789
|
}
|
|
4790
4790
|
return candidates[0];
|
|
4791
4791
|
}
|
|
4792
4792
|
function copyDir(src, dst) {
|
|
4793
|
-
|
|
4794
|
-
for (const ent of
|
|
4795
|
-
const s =
|
|
4796
|
-
const d =
|
|
4793
|
+
fs19.mkdirSync(dst, { recursive: true });
|
|
4794
|
+
for (const ent of fs19.readdirSync(src, { withFileTypes: true })) {
|
|
4795
|
+
const s = path18.join(src, ent.name);
|
|
4796
|
+
const d = path18.join(dst, ent.name);
|
|
4797
4797
|
if (ent.isDirectory()) copyDir(s, d);
|
|
4798
|
-
else if (ent.isFile())
|
|
4798
|
+
else if (ent.isFile()) fs19.copyFileSync(s, d);
|
|
4799
4799
|
}
|
|
4800
4800
|
}
|
|
4801
4801
|
var buildSyntheticPlugin;
|
|
@@ -4808,47 +4808,47 @@ var init_buildSyntheticPlugin = __esm({
|
|
|
4808
4808
|
if (!needsSynthetic) return;
|
|
4809
4809
|
const catalog = getPluginsCatalogRoot();
|
|
4810
4810
|
const runId = `${profile.name}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
4811
|
-
const root =
|
|
4812
|
-
|
|
4811
|
+
const root = path18.join(os3.tmpdir(), `kody-synth-${runId}`);
|
|
4812
|
+
fs19.mkdirSync(path18.join(root, ".claude-plugin"), { recursive: true });
|
|
4813
4813
|
const resolvePart = (bucket, entry) => {
|
|
4814
|
-
const local =
|
|
4815
|
-
if (
|
|
4816
|
-
const shared =
|
|
4817
|
-
if (
|
|
4818
|
-
const central =
|
|
4819
|
-
if (
|
|
4814
|
+
const local = path18.join(profile.dir, bucket, entry);
|
|
4815
|
+
if (fs19.existsSync(local)) return local;
|
|
4816
|
+
const shared = path18.resolve(profile.dir, "..", "..", "shared", bucket, entry);
|
|
4817
|
+
if (fs19.existsSync(shared)) return shared;
|
|
4818
|
+
const central = path18.join(catalog, bucket, entry);
|
|
4819
|
+
if (fs19.existsSync(central)) return central;
|
|
4820
4820
|
throw new Error(
|
|
4821
|
-
`buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${
|
|
4821
|
+
`buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${path18.dirname(shared)}/), or catalog (${catalog}/${bucket}/)`
|
|
4822
4822
|
);
|
|
4823
4823
|
};
|
|
4824
4824
|
if (cc.skills.length > 0) {
|
|
4825
|
-
const dst =
|
|
4826
|
-
|
|
4825
|
+
const dst = path18.join(root, "skills");
|
|
4826
|
+
fs19.mkdirSync(dst, { recursive: true });
|
|
4827
4827
|
for (const name of cc.skills) {
|
|
4828
|
-
copyDir(resolvePart("skills", name),
|
|
4828
|
+
copyDir(resolvePart("skills", name), path18.join(dst, name));
|
|
4829
4829
|
}
|
|
4830
4830
|
}
|
|
4831
4831
|
if (cc.commands.length > 0) {
|
|
4832
|
-
const dst =
|
|
4833
|
-
|
|
4832
|
+
const dst = path18.join(root, "commands");
|
|
4833
|
+
fs19.mkdirSync(dst, { recursive: true });
|
|
4834
4834
|
for (const name of cc.commands) {
|
|
4835
|
-
|
|
4835
|
+
fs19.copyFileSync(resolvePart("commands", `${name}.md`), path18.join(dst, `${name}.md`));
|
|
4836
4836
|
}
|
|
4837
4837
|
}
|
|
4838
4838
|
if (cc.hooks.length > 0) {
|
|
4839
|
-
const dst =
|
|
4840
|
-
|
|
4839
|
+
const dst = path18.join(root, "hooks");
|
|
4840
|
+
fs19.mkdirSync(dst, { recursive: true });
|
|
4841
4841
|
const merged = { hooks: {} };
|
|
4842
4842
|
for (const name of cc.hooks) {
|
|
4843
4843
|
const src = resolvePart("hooks", `${name}.json`);
|
|
4844
|
-
const parsed = JSON.parse(
|
|
4844
|
+
const parsed = JSON.parse(fs19.readFileSync(src, "utf-8"));
|
|
4845
4845
|
for (const [event, entries] of Object.entries(parsed.hooks ?? {})) {
|
|
4846
4846
|
if (!Array.isArray(entries)) continue;
|
|
4847
4847
|
if (!merged.hooks[event]) merged.hooks[event] = [];
|
|
4848
4848
|
merged.hooks[event].push(...entries);
|
|
4849
4849
|
}
|
|
4850
4850
|
}
|
|
4851
|
-
|
|
4851
|
+
fs19.writeFileSync(path18.join(dst, "hooks.json"), `${JSON.stringify(merged, null, 2)}
|
|
4852
4852
|
`);
|
|
4853
4853
|
}
|
|
4854
4854
|
const manifest = {
|
|
@@ -4858,7 +4858,7 @@ var init_buildSyntheticPlugin = __esm({
|
|
|
4858
4858
|
};
|
|
4859
4859
|
if (cc.skills.length > 0) manifest.skills = ["./skills/"];
|
|
4860
4860
|
if (cc.commands.length > 0) manifest.commands = ["./commands/"];
|
|
4861
|
-
|
|
4861
|
+
fs19.writeFileSync(path18.join(root, ".claude-plugin", "plugin.json"), `${JSON.stringify(manifest, null, 2)}
|
|
4862
4862
|
`);
|
|
4863
4863
|
ctx.data.syntheticPluginPath = root;
|
|
4864
4864
|
};
|
|
@@ -4866,8 +4866,8 @@ var init_buildSyntheticPlugin = __esm({
|
|
|
4866
4866
|
});
|
|
4867
4867
|
|
|
4868
4868
|
// src/subagents.ts
|
|
4869
|
-
import * as
|
|
4870
|
-
import * as
|
|
4869
|
+
import * as fs20 from "fs";
|
|
4870
|
+
import * as path19 from "path";
|
|
4871
4871
|
function splitFrontmatter(raw) {
|
|
4872
4872
|
const match = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(raw);
|
|
4873
4873
|
if (!match) return { fm: {}, body: raw.trim() };
|
|
@@ -4880,12 +4880,12 @@ function splitFrontmatter(raw) {
|
|
|
4880
4880
|
return { fm, body: (match[2] ?? "").trim() };
|
|
4881
4881
|
}
|
|
4882
4882
|
function resolveAgentFile2(profileDir, name) {
|
|
4883
|
-
const local =
|
|
4884
|
-
if (
|
|
4885
|
-
const shared =
|
|
4886
|
-
if (
|
|
4887
|
-
const central =
|
|
4888
|
-
if (
|
|
4883
|
+
const local = path19.join(profileDir, "agents", `${name}.md`);
|
|
4884
|
+
if (fs20.existsSync(local)) return local;
|
|
4885
|
+
const shared = path19.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
|
|
4886
|
+
if (fs20.existsSync(shared)) return shared;
|
|
4887
|
+
const central = path19.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
|
|
4888
|
+
if (fs20.existsSync(central)) return central;
|
|
4889
4889
|
throw new Error(
|
|
4890
4890
|
`loadSubagents: agent '${name}' not found in ${profileDir}/agents/, hydrated shared assets, or engine catalog`
|
|
4891
4891
|
);
|
|
@@ -4896,7 +4896,7 @@ function captureSubagentTemplates(profile) {
|
|
|
4896
4896
|
const out = {};
|
|
4897
4897
|
for (const name of names) {
|
|
4898
4898
|
try {
|
|
4899
|
-
out[name] =
|
|
4899
|
+
out[name] = fs20.readFileSync(resolveAgentFile2(profile.dir, name), "utf-8");
|
|
4900
4900
|
} catch {
|
|
4901
4901
|
}
|
|
4902
4902
|
}
|
|
@@ -4907,7 +4907,7 @@ function loadSubagents(profile) {
|
|
|
4907
4907
|
if (!names || names.length === 0) return void 0;
|
|
4908
4908
|
const agents = {};
|
|
4909
4909
|
for (const name of names) {
|
|
4910
|
-
const raw = profile.subagentTemplates?.[name] ??
|
|
4910
|
+
const raw = profile.subagentTemplates?.[name] ?? fs20.readFileSync(resolveAgentFile2(profile.dir, name), "utf-8");
|
|
4911
4911
|
const { fm, body } = splitFrontmatter(raw);
|
|
4912
4912
|
if (!body) throw new Error(`loadSubagents: agent '${name}' has an empty prompt body`);
|
|
4913
4913
|
const def = {
|
|
@@ -4931,16 +4931,16 @@ var init_subagents = __esm({
|
|
|
4931
4931
|
});
|
|
4932
4932
|
|
|
4933
4933
|
// src/profile.ts
|
|
4934
|
-
import { createHash as
|
|
4935
|
-
import * as
|
|
4936
|
-
import * as
|
|
4934
|
+
import { createHash as createHash4 } from "crypto";
|
|
4935
|
+
import * as fs21 from "fs";
|
|
4936
|
+
import * as path20 from "path";
|
|
4937
4937
|
function loadProfile(profilePath) {
|
|
4938
|
-
if (!
|
|
4938
|
+
if (!fs21.existsSync(profilePath)) {
|
|
4939
4939
|
throw new ProfileError(profilePath, "file not found");
|
|
4940
4940
|
}
|
|
4941
4941
|
let raw;
|
|
4942
4942
|
try {
|
|
4943
|
-
raw = JSON.parse(
|
|
4943
|
+
raw = JSON.parse(fs21.readFileSync(profilePath, "utf-8"));
|
|
4944
4944
|
} catch (err) {
|
|
4945
4945
|
throw new ProfileError(profilePath, `invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
4946
4946
|
}
|
|
@@ -4952,7 +4952,7 @@ function loadProfile(profilePath) {
|
|
|
4952
4952
|
const unknownKeys = Object.keys(r).filter((k) => !KNOWN_PROFILE_KEYS.has(k));
|
|
4953
4953
|
if (unknownKeys.length > 0) {
|
|
4954
4954
|
process.stderr.write(
|
|
4955
|
-
`[kody profile] ${
|
|
4955
|
+
`[kody profile] ${path20.basename(path20.dirname(profilePath))}: unknown top-level keys ignored: ${unknownKeys.join(", ")}
|
|
4956
4956
|
`
|
|
4957
4957
|
);
|
|
4958
4958
|
}
|
|
@@ -4962,7 +4962,7 @@ function loadProfile(profilePath) {
|
|
|
4962
4962
|
if (!refPath) {
|
|
4963
4963
|
throw new ProfileError(profilePath, `capability references unknown implementation '${execRef}'`);
|
|
4964
4964
|
}
|
|
4965
|
-
if (
|
|
4965
|
+
if (path20.resolve(refPath) === path20.resolve(profilePath)) {
|
|
4966
4966
|
} else {
|
|
4967
4967
|
const base = loadProfile(refPath);
|
|
4968
4968
|
return {
|
|
@@ -5060,8 +5060,8 @@ function loadProfile(profilePath) {
|
|
|
5060
5060
|
// Phase 5 in-process handoff opt-in. Default false; containers
|
|
5061
5061
|
// flip to true after end-to-end verification.
|
|
5062
5062
|
preloadContext: r.preloadContext === true,
|
|
5063
|
-
dir:
|
|
5064
|
-
promptTemplates: readPromptTemplates(
|
|
5063
|
+
dir: path20.dirname(profilePath),
|
|
5064
|
+
promptTemplates: readPromptTemplates(path20.dirname(profilePath))
|
|
5065
5065
|
};
|
|
5066
5066
|
if (lifecycle) {
|
|
5067
5067
|
applyLifecycle(profile, profilePath);
|
|
@@ -5096,19 +5096,19 @@ function loadProfile(profilePath) {
|
|
|
5096
5096
|
return profile;
|
|
5097
5097
|
}
|
|
5098
5098
|
function compileRuntimeDocument(runtimePath, document) {
|
|
5099
|
-
if (
|
|
5099
|
+
if (path20.basename(runtimePath) !== "runtime.json") return document;
|
|
5100
5100
|
if (document.adapter !== "kody-engine-profile") {
|
|
5101
5101
|
throw new ProfileError(runtimePath, "unsupported runtime adapter document");
|
|
5102
5102
|
}
|
|
5103
|
-
const implementationDir =
|
|
5104
|
-
const implementation = readJsonObject(
|
|
5105
|
-
const definitionsRoot2 =
|
|
5103
|
+
const implementationDir = path20.dirname(runtimePath);
|
|
5104
|
+
const implementation = readJsonObject(path20.join(implementationDir, "definition.json"), "Implementation definition");
|
|
5105
|
+
const definitionsRoot2 = path20.dirname(path20.dirname(implementationDir));
|
|
5106
5106
|
const capabilityId = implementation.capabilityRef && typeof implementation.capabilityRef === "object" && !Array.isArray(implementation.capabilityRef) ? implementation.capabilityRef.id : void 0;
|
|
5107
5107
|
if (typeof capabilityId !== "string" || !capabilityId) {
|
|
5108
5108
|
throw new ProfileError(runtimePath, "Implementation capabilityRef is invalid");
|
|
5109
5109
|
}
|
|
5110
5110
|
const capability = readJsonObject(
|
|
5111
|
-
|
|
5111
|
+
path20.join(definitionsRoot2, "capabilities", capabilityId, "definition.json"),
|
|
5112
5112
|
"Capability definition"
|
|
5113
5113
|
);
|
|
5114
5114
|
const {
|
|
@@ -5130,9 +5130,9 @@ function compileRuntimeDocument(runtimePath, document) {
|
|
|
5130
5130
|
agent: agentRef,
|
|
5131
5131
|
canonicalContract: {
|
|
5132
5132
|
capabilityId,
|
|
5133
|
-
capabilityRevision:
|
|
5133
|
+
capabilityRevision: createHash4("sha256").update(canonical2(capability)).digest("hex"),
|
|
5134
5134
|
implementationId: String(implementation.id),
|
|
5135
|
-
implementationRevision:
|
|
5135
|
+
implementationRevision: createHash4("sha256").update(canonical2(implementation)).digest("hex"),
|
|
5136
5136
|
inputSchema: capability.inputSchema,
|
|
5137
5137
|
outputSchema: capability.outputSchema
|
|
5138
5138
|
}
|
|
@@ -5147,7 +5147,7 @@ function canonical2(value) {
|
|
|
5147
5147
|
}
|
|
5148
5148
|
function readJsonObject(filePath, label) {
|
|
5149
5149
|
try {
|
|
5150
|
-
const value = JSON.parse(
|
|
5150
|
+
const value = JSON.parse(fs21.readFileSync(filePath, "utf-8"));
|
|
5151
5151
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5152
5152
|
throw new Error("must be an object");
|
|
5153
5153
|
}
|
|
@@ -5165,17 +5165,17 @@ function readPromptTemplates(dir) {
|
|
|
5165
5165
|
const out = {};
|
|
5166
5166
|
const read = (p) => {
|
|
5167
5167
|
try {
|
|
5168
|
-
out[p] =
|
|
5168
|
+
out[p] = fs21.readFileSync(p, "utf-8");
|
|
5169
5169
|
} catch {
|
|
5170
5170
|
}
|
|
5171
5171
|
};
|
|
5172
|
-
read(
|
|
5173
|
-
read(
|
|
5174
|
-
read(
|
|
5172
|
+
read(path20.join(dir, "prompt.md"));
|
|
5173
|
+
read(path20.join(dir, "capability.md"));
|
|
5174
|
+
read(path20.join(dir, "capability.md"));
|
|
5175
5175
|
try {
|
|
5176
|
-
const promptsDir =
|
|
5177
|
-
for (const ent of
|
|
5178
|
-
if (ent.endsWith(".md")) read(
|
|
5176
|
+
const promptsDir = path20.join(dir, "prompts");
|
|
5177
|
+
for (const ent of fs21.readdirSync(promptsDir)) {
|
|
5178
|
+
if (ent.endsWith(".md")) read(path20.join(promptsDir, ent));
|
|
5179
5179
|
}
|
|
5180
5180
|
} catch {
|
|
5181
5181
|
}
|
|
@@ -5950,16 +5950,16 @@ var init_state = __esm({
|
|
|
5950
5950
|
});
|
|
5951
5951
|
|
|
5952
5952
|
// src/prompt.ts
|
|
5953
|
-
import * as
|
|
5954
|
-
import * as
|
|
5953
|
+
import * as fs22 from "fs";
|
|
5954
|
+
import * as path21 from "path";
|
|
5955
5955
|
function loadProjectConventions(projectDir) {
|
|
5956
5956
|
const out = [];
|
|
5957
5957
|
for (const rel of CONVENTION_FILES) {
|
|
5958
|
-
const abs =
|
|
5959
|
-
if (!
|
|
5958
|
+
const abs = path21.join(projectDir, rel);
|
|
5959
|
+
if (!fs22.existsSync(abs)) continue;
|
|
5960
5960
|
let content;
|
|
5961
5961
|
try {
|
|
5962
|
-
content =
|
|
5962
|
+
content = fs22.readFileSync(abs, "utf-8");
|
|
5963
5963
|
} catch {
|
|
5964
5964
|
continue;
|
|
5965
5965
|
}
|
|
@@ -6194,8 +6194,8 @@ var loadMemoryContext_exports = {};
|
|
|
6194
6194
|
__export(loadMemoryContext_exports, {
|
|
6195
6195
|
loadMemoryContext: () => loadMemoryContext
|
|
6196
6196
|
});
|
|
6197
|
-
import * as
|
|
6198
|
-
import * as
|
|
6197
|
+
import * as fs23 from "fs";
|
|
6198
|
+
import * as path22 from "path";
|
|
6199
6199
|
function formatBlockFromBackend(docs) {
|
|
6200
6200
|
const pages = docs.flatMap((record2) => {
|
|
6201
6201
|
if (!record2.doc || typeof record2.doc !== "object") return [];
|
|
@@ -6218,21 +6218,21 @@ function collectPages(memoryAbs) {
|
|
|
6218
6218
|
walkMd(memoryAbs, (file) => {
|
|
6219
6219
|
let stat;
|
|
6220
6220
|
try {
|
|
6221
|
-
stat =
|
|
6221
|
+
stat = fs23.statSync(file);
|
|
6222
6222
|
} catch {
|
|
6223
6223
|
return;
|
|
6224
6224
|
}
|
|
6225
6225
|
let raw;
|
|
6226
6226
|
try {
|
|
6227
|
-
raw =
|
|
6227
|
+
raw = fs23.readFileSync(file, "utf-8");
|
|
6228
6228
|
} catch {
|
|
6229
6229
|
return;
|
|
6230
6230
|
}
|
|
6231
6231
|
const fm = raw.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
6232
|
-
const title = fm?.[1]?.match(/^title:\s*(.+)$/m)?.[1]?.trim() ??
|
|
6232
|
+
const title = fm?.[1]?.match(/^title:\s*(.+)$/m)?.[1]?.trim() ?? path22.basename(file, ".md");
|
|
6233
6233
|
const updated = fm?.[1]?.match(/^updated:\s*([0-9T:.+\-Z]+)/m)?.[1]?.trim() ?? "";
|
|
6234
6234
|
out.push({
|
|
6235
|
-
relPath:
|
|
6235
|
+
relPath: path22.relative(memoryAbs, file),
|
|
6236
6236
|
title,
|
|
6237
6237
|
updated,
|
|
6238
6238
|
content: raw.length > PER_PAGE_MAX_BYTES ? raw.slice(0, PER_PAGE_MAX_BYTES) + TRUNCATED_SUFFIX2 : raw,
|
|
@@ -6300,16 +6300,16 @@ function walkMd(root, visit) {
|
|
|
6300
6300
|
const dir = stack.pop();
|
|
6301
6301
|
let names;
|
|
6302
6302
|
try {
|
|
6303
|
-
names =
|
|
6303
|
+
names = fs23.readdirSync(dir);
|
|
6304
6304
|
} catch {
|
|
6305
6305
|
continue;
|
|
6306
6306
|
}
|
|
6307
6307
|
for (const name of names) {
|
|
6308
6308
|
if (name.startsWith(".")) continue;
|
|
6309
|
-
const full =
|
|
6309
|
+
const full = path22.join(dir, name);
|
|
6310
6310
|
let stat;
|
|
6311
6311
|
try {
|
|
6312
|
-
stat =
|
|
6312
|
+
stat = fs23.statSync(full);
|
|
6313
6313
|
} catch {
|
|
6314
6314
|
continue;
|
|
6315
6315
|
}
|
|
@@ -6344,8 +6344,8 @@ var init_loadMemoryContext = __esm({
|
|
|
6344
6344
|
}
|
|
6345
6345
|
return;
|
|
6346
6346
|
}
|
|
6347
|
-
const memoryAbs =
|
|
6348
|
-
if (!
|
|
6347
|
+
const memoryAbs = path22.join(ctx.cwd, MEMORY_DIR_RELATIVE);
|
|
6348
|
+
if (!fs23.existsSync(memoryAbs)) {
|
|
6349
6349
|
ctx.data.memoryContext = "";
|
|
6350
6350
|
return;
|
|
6351
6351
|
}
|
|
@@ -6389,11 +6389,11 @@ var init_loadCoverageRules = __esm({
|
|
|
6389
6389
|
|
|
6390
6390
|
// src/container.ts
|
|
6391
6391
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
6392
|
-
import * as
|
|
6392
|
+
import * as fs24 from "fs";
|
|
6393
6393
|
function getProfileInputsForChild(profileName, _cwd) {
|
|
6394
6394
|
try {
|
|
6395
6395
|
const profilePath = resolveProfilePath(profileName);
|
|
6396
|
-
if (!
|
|
6396
|
+
if (!fs24.existsSync(profilePath)) return null;
|
|
6397
6397
|
return loadProfile(profilePath).inputs;
|
|
6398
6398
|
} catch {
|
|
6399
6399
|
return null;
|
|
@@ -6857,10 +6857,10 @@ var init_lifecycleLabels = __esm({
|
|
|
6857
6857
|
|
|
6858
6858
|
// src/litellm.ts
|
|
6859
6859
|
import { execFileSync as execFileSync4, spawn as spawn4 } from "child_process";
|
|
6860
|
-
import * as
|
|
6860
|
+
import * as fs25 from "fs";
|
|
6861
6861
|
import * as net from "net";
|
|
6862
6862
|
import * as os4 from "os";
|
|
6863
|
-
import * as
|
|
6863
|
+
import * as path23 from "path";
|
|
6864
6864
|
async function checkLitellmHealth(url) {
|
|
6865
6865
|
try {
|
|
6866
6866
|
const response = await fetch(`${url}/health`, { signal: AbortSignal.timeout(3e3) });
|
|
@@ -6930,7 +6930,7 @@ function locateLitellmScript() {
|
|
|
6930
6930
|
}
|
|
6931
6931
|
function resolveLitellmCommand() {
|
|
6932
6932
|
const imageScript = "/opt/venv/bin/litellm";
|
|
6933
|
-
if (
|
|
6933
|
+
if (fs25.existsSync(imageScript)) return imageScript;
|
|
6934
6934
|
try {
|
|
6935
6935
|
execFileSync4("which", ["litellm"], { timeout: 3e3, stdio: "pipe" });
|
|
6936
6936
|
return "litellm";
|
|
@@ -6966,13 +6966,13 @@ async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL
|
|
|
6966
6966
|
const spawnProxy = () => {
|
|
6967
6967
|
const portMatch = activeUrl.match(/:(\d+)/);
|
|
6968
6968
|
const port = portMatch ? portMatch[1] : "4000";
|
|
6969
|
-
const configPath =
|
|
6970
|
-
|
|
6969
|
+
const configPath = path23.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.yaml`);
|
|
6970
|
+
fs25.writeFileSync(configPath, generateLitellmConfigYaml(model));
|
|
6971
6971
|
const args = ["--config", configPath, "--port", port];
|
|
6972
|
-
const nextLogPath =
|
|
6973
|
-
const outFd =
|
|
6972
|
+
const nextLogPath = path23.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.log`);
|
|
6973
|
+
const outFd = fs25.openSync(nextLogPath, "w");
|
|
6974
6974
|
child = spawn4(cmd, args, { stdio: ["ignore", outFd, outFd], detached: true, env: childEnv });
|
|
6975
|
-
|
|
6975
|
+
fs25.closeSync(outFd);
|
|
6976
6976
|
logPath = nextLogPath;
|
|
6977
6977
|
};
|
|
6978
6978
|
const waitForHealth = async () => {
|
|
@@ -6986,7 +6986,7 @@ async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL
|
|
|
6986
6986
|
const readLogTail = () => {
|
|
6987
6987
|
if (!logPath) return "";
|
|
6988
6988
|
try {
|
|
6989
|
-
return
|
|
6989
|
+
return fs25.readFileSync(logPath, "utf-8").slice(-2e3);
|
|
6990
6990
|
} catch {
|
|
6991
6991
|
return "";
|
|
6992
6992
|
}
|
|
@@ -7069,10 +7069,10 @@ function canListen(port, host) {
|
|
|
7069
7069
|
});
|
|
7070
7070
|
}
|
|
7071
7071
|
function readDotenvApiKeys(projectDir) {
|
|
7072
|
-
const dotenvPath =
|
|
7073
|
-
if (!
|
|
7072
|
+
const dotenvPath = path23.join(projectDir, ".env");
|
|
7073
|
+
if (!fs25.existsSync(dotenvPath)) return {};
|
|
7074
7074
|
const result = {};
|
|
7075
|
-
for (const rawLine of
|
|
7075
|
+
for (const rawLine of fs25.readFileSync(dotenvPath, "utf-8").split("\n")) {
|
|
7076
7076
|
const line = rawLine.trim();
|
|
7077
7077
|
if (!line || line.startsWith("#")) continue;
|
|
7078
7078
|
const match = line.match(/^([A-Z_][A-Z0-9_]*_API_KEY)=(.*)$/);
|
|
@@ -7472,8 +7472,8 @@ var init_pushWithRetry = __esm({
|
|
|
7472
7472
|
|
|
7473
7473
|
// src/commit.ts
|
|
7474
7474
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
7475
|
-
import * as
|
|
7476
|
-
import * as
|
|
7475
|
+
import * as fs26 from "fs";
|
|
7476
|
+
import * as path24 from "path";
|
|
7477
7477
|
function isGitHubYamlPath(filePath) {
|
|
7478
7478
|
const normalized = filePath.replace(/^\.\/+/, "");
|
|
7479
7479
|
return normalized.startsWith(".github/") && /\.ya?ml$/i.test(normalized);
|
|
@@ -7515,18 +7515,18 @@ function ensureGitIdentity(cwd) {
|
|
|
7515
7515
|
}
|
|
7516
7516
|
function abortUnfinishedGitOps(cwd) {
|
|
7517
7517
|
const aborted = [];
|
|
7518
|
-
const gitDir =
|
|
7519
|
-
if (!
|
|
7520
|
-
if (
|
|
7518
|
+
const gitDir = path24.join(cwd ?? process.cwd(), ".git");
|
|
7519
|
+
if (!fs26.existsSync(gitDir)) return aborted;
|
|
7520
|
+
if (fs26.existsSync(path24.join(gitDir, "MERGE_HEAD"))) {
|
|
7521
7521
|
if (tryGit(["merge", "--abort"], cwd)) aborted.push("merge");
|
|
7522
7522
|
}
|
|
7523
|
-
if (
|
|
7523
|
+
if (fs26.existsSync(path24.join(gitDir, "CHERRY_PICK_HEAD"))) {
|
|
7524
7524
|
if (tryGit(["cherry-pick", "--abort"], cwd)) aborted.push("cherry-pick");
|
|
7525
7525
|
}
|
|
7526
|
-
if (
|
|
7526
|
+
if (fs26.existsSync(path24.join(gitDir, "REVERT_HEAD"))) {
|
|
7527
7527
|
if (tryGit(["revert", "--abort"], cwd)) aborted.push("revert");
|
|
7528
7528
|
}
|
|
7529
|
-
if (
|
|
7529
|
+
if (fs26.existsSync(path24.join(gitDir, "rebase-merge")) || fs26.existsSync(path24.join(gitDir, "rebase-apply"))) {
|
|
7530
7530
|
if (tryGit(["rebase", "--abort"], cwd)) aborted.push("rebase");
|
|
7531
7531
|
}
|
|
7532
7532
|
try {
|
|
@@ -7583,7 +7583,7 @@ function normalizeCommitMessage(raw) {
|
|
|
7583
7583
|
function commitAndPush(branch, agentMessage, cwd) {
|
|
7584
7584
|
const allChanged = listChangedFiles(cwd);
|
|
7585
7585
|
const allowedFiles = allChanged.filter((f) => !isForbiddenPath(f));
|
|
7586
|
-
const mergeHeadExists =
|
|
7586
|
+
const mergeHeadExists = fs26.existsSync(path24.join(cwd ?? process.cwd(), ".git", "MERGE_HEAD"));
|
|
7587
7587
|
if (allowedFiles.length === 0 && !mergeHeadExists) {
|
|
7588
7588
|
return { committed: false, pushed: false, sha: "", message: "" };
|
|
7589
7589
|
}
|
|
@@ -8223,7 +8223,7 @@ var init_state2 = __esm({
|
|
|
8223
8223
|
});
|
|
8224
8224
|
|
|
8225
8225
|
// src/goal/runLog.ts
|
|
8226
|
-
import * as
|
|
8226
|
+
import * as fs27 from "fs";
|
|
8227
8227
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
8228
8228
|
const logs = goalRunLogs(data);
|
|
8229
8229
|
const existing = logs[goalId];
|
|
@@ -8565,8 +8565,8 @@ function readGithubEvent() {
|
|
|
8565
8565
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
8566
8566
|
if (!eventPath) return null;
|
|
8567
8567
|
try {
|
|
8568
|
-
if (!
|
|
8569
|
-
const parsed = JSON.parse(
|
|
8568
|
+
if (!fs27.existsSync(eventPath)) return null;
|
|
8569
|
+
const parsed = JSON.parse(fs27.readFileSync(eventPath, "utf-8"));
|
|
8570
8570
|
return recordValue3(parsed);
|
|
8571
8571
|
} catch {
|
|
8572
8572
|
return null;
|
|
@@ -8676,8 +8676,8 @@ var init_stateStore = __esm({
|
|
|
8676
8676
|
});
|
|
8677
8677
|
|
|
8678
8678
|
// src/goal/targetLoopResolution.ts
|
|
8679
|
-
import * as
|
|
8680
|
-
import * as
|
|
8679
|
+
import * as fs28 from "fs";
|
|
8680
|
+
import * as path25 from "path";
|
|
8681
8681
|
async function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
|
|
8682
8682
|
const targetId = loopGoal.loopTarget?.id.trim() ?? "";
|
|
8683
8683
|
assertSafeGoalId(targetId, "loop target");
|
|
@@ -8755,11 +8755,11 @@ function goalInstanceTime(state) {
|
|
|
8755
8755
|
return Number.isNaN(parsed) ? 0 : parsed;
|
|
8756
8756
|
}
|
|
8757
8757
|
function loadGoalTemplate(cwd, targetId) {
|
|
8758
|
-
return readJsonObject2(
|
|
8758
|
+
return readJsonObject2(path25.join(cwd, ".kody-engine", "definitions", "goals", targetId, "state.json"));
|
|
8759
8759
|
}
|
|
8760
8760
|
function readJsonObject2(filePath) {
|
|
8761
|
-
if (!
|
|
8762
|
-
const parsed = JSON.parse(
|
|
8761
|
+
if (!fs28.existsSync(filePath)) return null;
|
|
8762
|
+
const parsed = JSON.parse(fs28.readFileSync(filePath, "utf8"));
|
|
8763
8763
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
8764
8764
|
throw new Error(`goal template ${filePath} must be a JSON object`);
|
|
8765
8765
|
}
|
|
@@ -9278,8 +9278,8 @@ var init_workflowValidation = __esm({
|
|
|
9278
9278
|
});
|
|
9279
9279
|
|
|
9280
9280
|
// src/workflowDefinitions.ts
|
|
9281
|
-
import * as
|
|
9282
|
-
import * as
|
|
9281
|
+
import * as fs29 from "fs";
|
|
9282
|
+
import * as path26 from "path";
|
|
9283
9283
|
function isWorkflowDefinitionId(value) {
|
|
9284
9284
|
return WORKFLOW_ID_PATTERN.test(value);
|
|
9285
9285
|
}
|
|
@@ -9323,12 +9323,12 @@ function readWorkflowDefinition(_config, cwd, id) {
|
|
|
9323
9323
|
const root = cwd ?? process.cwd();
|
|
9324
9324
|
const relativePath = workflowDefinitionPath(id);
|
|
9325
9325
|
const candidates = [
|
|
9326
|
-
|
|
9327
|
-
|
|
9326
|
+
path26.join(root, ".kody-engine", "runtime", relativePath),
|
|
9327
|
+
path26.join(root, ".kody-engine", "definitions", relativePath)
|
|
9328
9328
|
];
|
|
9329
9329
|
for (const filePath of candidates) {
|
|
9330
|
-
if (!
|
|
9331
|
-
const workflow = parseWorkflowDefinition(
|
|
9330
|
+
if (!fs29.existsSync(filePath)) continue;
|
|
9331
|
+
const workflow = parseWorkflowDefinition(fs29.readFileSync(filePath, "utf8"));
|
|
9332
9332
|
if (workflow) return workflow;
|
|
9333
9333
|
}
|
|
9334
9334
|
return null;
|
|
@@ -9336,7 +9336,7 @@ function readWorkflowDefinition(_config, cwd, id) {
|
|
|
9336
9336
|
function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
|
|
9337
9337
|
return {
|
|
9338
9338
|
slug: id,
|
|
9339
|
-
dir:
|
|
9339
|
+
dir: path26.dirname(source),
|
|
9340
9340
|
profilePath: source,
|
|
9341
9341
|
bodyPath: source,
|
|
9342
9342
|
title: workflow.name,
|
|
@@ -9541,8 +9541,8 @@ var init_backendStateBackend = __esm({
|
|
|
9541
9541
|
});
|
|
9542
9542
|
|
|
9543
9543
|
// src/scripts/jobState/localFileBackend.ts
|
|
9544
|
-
import * as
|
|
9545
|
-
import * as
|
|
9544
|
+
import * as fs30 from "fs";
|
|
9545
|
+
import * as path27 from "path";
|
|
9546
9546
|
function sanitizeKey(s) {
|
|
9547
9547
|
return s.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
9548
9548
|
}
|
|
@@ -9598,7 +9598,7 @@ var init_localFileBackend = __esm({
|
|
|
9598
9598
|
if (!opts.owner || !opts.repo) throw new Error("LocalFileBackend: owner and repo are required");
|
|
9599
9599
|
this.cwd = opts.cwd;
|
|
9600
9600
|
this.jobsDir = opts.jobsDir;
|
|
9601
|
-
this.absDir =
|
|
9601
|
+
this.absDir = path27.resolve(opts.cwd, opts.jobsDir);
|
|
9602
9602
|
this.owner = opts.owner;
|
|
9603
9603
|
this.repo = opts.repo;
|
|
9604
9604
|
this.cache = opts.cache ?? defaultCacheAdapter();
|
|
@@ -9613,7 +9613,7 @@ var init_localFileBackend = __esm({
|
|
|
9613
9613
|
`);
|
|
9614
9614
|
return;
|
|
9615
9615
|
}
|
|
9616
|
-
|
|
9616
|
+
fs30.mkdirSync(this.absDir, { recursive: true });
|
|
9617
9617
|
const prefix = this.cacheKeyPrefix();
|
|
9618
9618
|
const probeKey = `${prefix}probe-${Date.now()}`;
|
|
9619
9619
|
try {
|
|
@@ -9642,7 +9642,7 @@ var init_localFileBackend = __esm({
|
|
|
9642
9642
|
`);
|
|
9643
9643
|
return;
|
|
9644
9644
|
}
|
|
9645
|
-
if (!
|
|
9645
|
+
if (!fs30.existsSync(this.absDir)) {
|
|
9646
9646
|
return;
|
|
9647
9647
|
}
|
|
9648
9648
|
const key = `${this.cacheKeyPrefix()}${process.env.GITHUB_RUN_ID ?? "norunid"}-${Date.now()}`;
|
|
@@ -9658,11 +9658,11 @@ var init_localFileBackend = __esm({
|
|
|
9658
9658
|
}
|
|
9659
9659
|
load(slug) {
|
|
9660
9660
|
const relPath = stateFilePath(this.jobsDir, slug);
|
|
9661
|
-
const absPath =
|
|
9662
|
-
if (!
|
|
9661
|
+
const absPath = path27.resolve(this.cwd, relPath);
|
|
9662
|
+
if (!fs30.existsSync(absPath)) {
|
|
9663
9663
|
return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
9664
9664
|
}
|
|
9665
|
-
const raw =
|
|
9665
|
+
const raw = fs30.readFileSync(absPath, "utf-8");
|
|
9666
9666
|
let parsed;
|
|
9667
9667
|
try {
|
|
9668
9668
|
parsed = JSON.parse(raw);
|
|
@@ -9679,13 +9679,13 @@ var init_localFileBackend = __esm({
|
|
|
9679
9679
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) {
|
|
9680
9680
|
return false;
|
|
9681
9681
|
}
|
|
9682
|
-
const absPath =
|
|
9683
|
-
|
|
9682
|
+
const absPath = path27.resolve(this.cwd, loaded.path);
|
|
9683
|
+
fs30.mkdirSync(path27.dirname(absPath), { recursive: true });
|
|
9684
9684
|
const body = `${JSON.stringify(next, null, 2)}
|
|
9685
9685
|
`;
|
|
9686
9686
|
const tmpPath = `${absPath}.${process.pid}.tmp`;
|
|
9687
|
-
|
|
9688
|
-
|
|
9687
|
+
fs30.writeFileSync(tmpPath, body, "utf-8");
|
|
9688
|
+
fs30.renameSync(tmpPath, absPath);
|
|
9689
9689
|
return true;
|
|
9690
9690
|
}
|
|
9691
9691
|
cacheKeyPrefix() {
|
|
@@ -9717,7 +9717,7 @@ var init_jobState = __esm({
|
|
|
9717
9717
|
});
|
|
9718
9718
|
|
|
9719
9719
|
// src/scripts/goalCapabilityScheduling.ts
|
|
9720
|
-
import * as
|
|
9720
|
+
import * as path28 from "path";
|
|
9721
9721
|
function isCapabilityCadenceGoal(goal, extra) {
|
|
9722
9722
|
return extra.scheduleMode === "agentLoop" || extra.scheduler === "agentLoop" || goal.type === "standing" && goal.capabilities.length > 0;
|
|
9723
9723
|
}
|
|
@@ -9773,7 +9773,7 @@ function planTargetLoopSchedule(opts) {
|
|
|
9773
9773
|
}
|
|
9774
9774
|
async function planGoalCapabilitySchedule(opts) {
|
|
9775
9775
|
const jobsDir = opts.jobsDir ?? capabilitiesRoot(opts.cwd);
|
|
9776
|
-
const jobsRoot =
|
|
9776
|
+
const jobsRoot = path28.resolve(opts.cwd, jobsDir);
|
|
9777
9777
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
9778
9778
|
const at = now.toISOString();
|
|
9779
9779
|
const backend = resolveBackend({ config: opts.config, cwd: opts.cwd, jobsDir });
|
|
@@ -11588,8 +11588,8 @@ var init_classifyByLabel = __esm({
|
|
|
11588
11588
|
});
|
|
11589
11589
|
|
|
11590
11590
|
// src/scripts/commitAndPush.ts
|
|
11591
|
-
import * as
|
|
11592
|
-
import * as
|
|
11591
|
+
import * as fs31 from "fs";
|
|
11592
|
+
import * as path29 from "path";
|
|
11593
11593
|
function sentinelPathForStage(cwd, profileName) {
|
|
11594
11594
|
const runId = resolveRunId();
|
|
11595
11595
|
return runtimeStatePath(cwd, "agent-runs", runId, `commit-${profileName}.lock`);
|
|
@@ -11610,9 +11610,9 @@ var init_commitAndPush = __esm({
|
|
|
11610
11610
|
}
|
|
11611
11611
|
const idempotencyEnabled = process.env.KODY_COMMIT_IDEMPOTENCY !== "0";
|
|
11612
11612
|
const sentinel = idempotencyEnabled ? sentinelPathForStage(ctx.cwd, profile.name) : null;
|
|
11613
|
-
if (sentinel &&
|
|
11613
|
+
if (sentinel && fs31.existsSync(sentinel)) {
|
|
11614
11614
|
try {
|
|
11615
|
-
const replay = JSON.parse(
|
|
11615
|
+
const replay = JSON.parse(fs31.readFileSync(sentinel, "utf-8"));
|
|
11616
11616
|
ctx.data.commitResult = replay.commitResult ?? { committed: false, pushed: false };
|
|
11617
11617
|
if (Array.isArray(replay.changedFiles)) ctx.data.changedFiles = replay.changedFiles;
|
|
11618
11618
|
if (typeof replay.hasCommitsAhead === "boolean") ctx.data.hasCommitsAhead = replay.hasCommitsAhead;
|
|
@@ -11672,8 +11672,8 @@ var init_commitAndPush = __esm({
|
|
|
11672
11672
|
const result = ctx.data.commitResult;
|
|
11673
11673
|
if (sentinel && result?.committed) {
|
|
11674
11674
|
try {
|
|
11675
|
-
|
|
11676
|
-
|
|
11675
|
+
fs31.mkdirSync(path29.dirname(sentinel), { recursive: true });
|
|
11676
|
+
fs31.writeFileSync(
|
|
11677
11677
|
sentinel,
|
|
11678
11678
|
JSON.stringify(
|
|
11679
11679
|
{
|
|
@@ -11767,8 +11767,8 @@ var init_commitGoalState = __esm({
|
|
|
11767
11767
|
});
|
|
11768
11768
|
|
|
11769
11769
|
// src/scripts/composePrompt.ts
|
|
11770
|
-
import * as
|
|
11771
|
-
import * as
|
|
11770
|
+
import * as fs32 from "fs";
|
|
11771
|
+
import * as path30 from "path";
|
|
11772
11772
|
function fenceUntrusted(value) {
|
|
11773
11773
|
if (value.trim().length === 0) return value;
|
|
11774
11774
|
const safe = value.replace(/-{3,}\s*END UNTRUSTED INPUT\s*-{3,}/gi, "[END UNTRUSTED INPUT]");
|
|
@@ -11892,10 +11892,10 @@ var init_composePrompt = __esm({
|
|
|
11892
11892
|
const explicit = ctx.data.promptTemplate;
|
|
11893
11893
|
const mode = ctx.args.mode;
|
|
11894
11894
|
const candidates = [
|
|
11895
|
-
explicit ?
|
|
11896
|
-
mode ?
|
|
11897
|
-
|
|
11898
|
-
|
|
11895
|
+
explicit ? path30.join(profile.dir, explicit) : null,
|
|
11896
|
+
mode ? path30.join(profile.dir, "prompts", `${mode}.md`) : null,
|
|
11897
|
+
path30.join(profile.dir, "prompt.md"),
|
|
11898
|
+
path30.join(profile.dir, "capability.md")
|
|
11899
11899
|
].filter(Boolean);
|
|
11900
11900
|
let templatePath = "";
|
|
11901
11901
|
let template = "";
|
|
@@ -11908,7 +11908,7 @@ var init_composePrompt = __esm({
|
|
|
11908
11908
|
break;
|
|
11909
11909
|
}
|
|
11910
11910
|
try {
|
|
11911
|
-
template =
|
|
11911
|
+
template = fs32.readFileSync(c, "utf-8");
|
|
11912
11912
|
templatePath = c;
|
|
11913
11913
|
break;
|
|
11914
11914
|
} catch (err) {
|
|
@@ -11919,7 +11919,7 @@ var init_composePrompt = __esm({
|
|
|
11919
11919
|
if (!templatePath) {
|
|
11920
11920
|
let dirState;
|
|
11921
11921
|
try {
|
|
11922
|
-
dirState = `dir contents: [${
|
|
11922
|
+
dirState = `dir contents: [${fs32.readdirSync(profile.dir).join(", ")}]`;
|
|
11923
11923
|
} catch (err) {
|
|
11924
11924
|
dirState = `readdir(${profile.dir}) failed: ${err?.code ?? String(err)}`;
|
|
11925
11925
|
}
|
|
@@ -12653,19 +12653,19 @@ var init_deriveQaScopeFromIssue = __esm({
|
|
|
12653
12653
|
|
|
12654
12654
|
// src/scripts/diagMcp.ts
|
|
12655
12655
|
import { execFileSync as execFileSync9 } from "child_process";
|
|
12656
|
-
import * as
|
|
12656
|
+
import * as fs33 from "fs";
|
|
12657
12657
|
import * as os5 from "os";
|
|
12658
|
-
import * as
|
|
12658
|
+
import * as path31 from "path";
|
|
12659
12659
|
var diagMcp;
|
|
12660
12660
|
var init_diagMcp = __esm({
|
|
12661
12661
|
"src/scripts/diagMcp.ts"() {
|
|
12662
12662
|
"use strict";
|
|
12663
12663
|
diagMcp = async (_ctx) => {
|
|
12664
12664
|
const home = os5.homedir();
|
|
12665
|
-
const cacheDir =
|
|
12665
|
+
const cacheDir = path31.join(home, ".cache", "ms-playwright");
|
|
12666
12666
|
let entries = [];
|
|
12667
12667
|
try {
|
|
12668
|
-
entries =
|
|
12668
|
+
entries = fs33.readdirSync(cacheDir);
|
|
12669
12669
|
} catch {
|
|
12670
12670
|
}
|
|
12671
12671
|
const hasChromium = entries.some((e) => e.startsWith("chromium"));
|
|
@@ -12693,13 +12693,13 @@ var init_diagMcp = __esm({
|
|
|
12693
12693
|
});
|
|
12694
12694
|
|
|
12695
12695
|
// src/scripts/frameworkDetectors.ts
|
|
12696
|
-
import * as
|
|
12697
|
-
import * as
|
|
12696
|
+
import * as fs34 from "fs";
|
|
12697
|
+
import * as path32 from "path";
|
|
12698
12698
|
function detectFrameworks(cwd) {
|
|
12699
12699
|
const out = [];
|
|
12700
12700
|
let deps = {};
|
|
12701
12701
|
try {
|
|
12702
|
-
const pkg = JSON.parse(
|
|
12702
|
+
const pkg = JSON.parse(fs34.readFileSync(path32.join(cwd, "package.json"), "utf-8"));
|
|
12703
12703
|
deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
12704
12704
|
} catch {
|
|
12705
12705
|
return out;
|
|
@@ -12736,25 +12736,25 @@ function detectFrameworks(cwd) {
|
|
|
12736
12736
|
}
|
|
12737
12737
|
function findFile(cwd, candidates) {
|
|
12738
12738
|
for (const c of candidates) {
|
|
12739
|
-
if (
|
|
12739
|
+
if (fs34.existsSync(path32.join(cwd, c))) return c;
|
|
12740
12740
|
}
|
|
12741
12741
|
return null;
|
|
12742
12742
|
}
|
|
12743
12743
|
function discoverPayloadCollections(cwd) {
|
|
12744
12744
|
const out = [];
|
|
12745
12745
|
for (const dir of COLLECTION_DIRS) {
|
|
12746
|
-
const full =
|
|
12747
|
-
if (!
|
|
12746
|
+
const full = path32.join(cwd, dir);
|
|
12747
|
+
if (!fs34.existsSync(full)) continue;
|
|
12748
12748
|
let files;
|
|
12749
12749
|
try {
|
|
12750
|
-
files =
|
|
12750
|
+
files = fs34.readdirSync(full).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
12751
12751
|
} catch {
|
|
12752
12752
|
continue;
|
|
12753
12753
|
}
|
|
12754
12754
|
for (const file of files) {
|
|
12755
12755
|
try {
|
|
12756
|
-
const filePath =
|
|
12757
|
-
const content =
|
|
12756
|
+
const filePath = path32.join(full, file);
|
|
12757
|
+
const content = fs34.readFileSync(filePath, "utf-8").slice(0, 1e4);
|
|
12758
12758
|
const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
|
|
12759
12759
|
if (!slugMatch) continue;
|
|
12760
12760
|
const slug = slugMatch[1];
|
|
@@ -12768,7 +12768,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
12768
12768
|
out.push({
|
|
12769
12769
|
name,
|
|
12770
12770
|
slug,
|
|
12771
|
-
filePath:
|
|
12771
|
+
filePath: path32.relative(cwd, filePath),
|
|
12772
12772
|
fields: fields.slice(0, 20),
|
|
12773
12773
|
hasAdmin
|
|
12774
12774
|
});
|
|
@@ -12781,28 +12781,28 @@ function discoverPayloadCollections(cwd) {
|
|
|
12781
12781
|
function discoverAdminComponents(cwd, collections) {
|
|
12782
12782
|
const out = [];
|
|
12783
12783
|
for (const dir of ADMIN_COMPONENT_DIRS) {
|
|
12784
|
-
const full =
|
|
12785
|
-
if (!
|
|
12784
|
+
const full = path32.join(cwd, dir);
|
|
12785
|
+
if (!fs34.existsSync(full)) continue;
|
|
12786
12786
|
let entries;
|
|
12787
12787
|
try {
|
|
12788
|
-
entries =
|
|
12788
|
+
entries = fs34.readdirSync(full, { withFileTypes: true });
|
|
12789
12789
|
} catch {
|
|
12790
12790
|
continue;
|
|
12791
12791
|
}
|
|
12792
12792
|
for (const entry of entries) {
|
|
12793
|
-
const entryPath =
|
|
12793
|
+
const entryPath = path32.join(full, entry.name);
|
|
12794
12794
|
let name;
|
|
12795
12795
|
let filePath;
|
|
12796
12796
|
if (entry.isDirectory()) {
|
|
12797
12797
|
const indexFile = ["index.tsx", "index.ts", "index.jsx", "index.js"].find(
|
|
12798
|
-
(f) =>
|
|
12798
|
+
(f) => fs34.existsSync(path32.join(entryPath, f))
|
|
12799
12799
|
);
|
|
12800
12800
|
if (!indexFile) continue;
|
|
12801
12801
|
name = entry.name;
|
|
12802
|
-
filePath =
|
|
12802
|
+
filePath = path32.relative(cwd, path32.join(entryPath, indexFile));
|
|
12803
12803
|
} else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
|
|
12804
12804
|
name = entry.name.replace(/\.(tsx?|jsx?)$/, "");
|
|
12805
|
-
filePath =
|
|
12805
|
+
filePath = path32.relative(cwd, entryPath);
|
|
12806
12806
|
} else {
|
|
12807
12807
|
continue;
|
|
12808
12808
|
}
|
|
@@ -12810,7 +12810,7 @@ function discoverAdminComponents(cwd, collections) {
|
|
|
12810
12810
|
if (collections) {
|
|
12811
12811
|
for (const col of collections) {
|
|
12812
12812
|
try {
|
|
12813
|
-
const colContent =
|
|
12813
|
+
const colContent = fs34.readFileSync(path32.join(cwd, col.filePath), "utf-8");
|
|
12814
12814
|
if (colContent.includes(name)) {
|
|
12815
12815
|
usedInCollection = col.slug;
|
|
12816
12816
|
break;
|
|
@@ -12828,8 +12828,8 @@ function scanApiRoutes(cwd) {
|
|
|
12828
12828
|
const out = [];
|
|
12829
12829
|
const appDirs = ["src/app", "app"];
|
|
12830
12830
|
for (const appDir of appDirs) {
|
|
12831
|
-
const apiDir =
|
|
12832
|
-
if (!
|
|
12831
|
+
const apiDir = path32.join(cwd, appDir, "api");
|
|
12832
|
+
if (!fs34.existsSync(apiDir)) continue;
|
|
12833
12833
|
walkApiRoutes(apiDir, "/api", cwd, out);
|
|
12834
12834
|
break;
|
|
12835
12835
|
}
|
|
@@ -12838,14 +12838,14 @@ function scanApiRoutes(cwd) {
|
|
|
12838
12838
|
function walkApiRoutes(dir, prefix, cwd, out) {
|
|
12839
12839
|
let entries;
|
|
12840
12840
|
try {
|
|
12841
|
-
entries =
|
|
12841
|
+
entries = fs34.readdirSync(dir, { withFileTypes: true });
|
|
12842
12842
|
} catch {
|
|
12843
12843
|
return;
|
|
12844
12844
|
}
|
|
12845
12845
|
const routeFile = entries.find((e) => e.isFile() && /^route\.(ts|js|tsx|jsx)$/.test(e.name));
|
|
12846
12846
|
if (routeFile) {
|
|
12847
12847
|
try {
|
|
12848
|
-
const content =
|
|
12848
|
+
const content = fs34.readFileSync(path32.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
|
|
12849
12849
|
const methods = HTTP_METHODS.filter(
|
|
12850
12850
|
(m) => new RegExp(`export\\s+(?:async\\s+)?function\\s+${m}\\b`).test(content)
|
|
12851
12851
|
);
|
|
@@ -12853,7 +12853,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
12853
12853
|
out.push({
|
|
12854
12854
|
path: prefix,
|
|
12855
12855
|
methods,
|
|
12856
|
-
filePath:
|
|
12856
|
+
filePath: path32.relative(cwd, path32.join(dir, routeFile.name))
|
|
12857
12857
|
});
|
|
12858
12858
|
}
|
|
12859
12859
|
} catch {
|
|
@@ -12864,7 +12864,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
12864
12864
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
12865
12865
|
let segment = entry.name;
|
|
12866
12866
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
12867
|
-
walkApiRoutes(
|
|
12867
|
+
walkApiRoutes(path32.join(dir, entry.name), prefix, cwd, out);
|
|
12868
12868
|
continue;
|
|
12869
12869
|
}
|
|
12870
12870
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -12872,16 +12872,16 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
12872
12872
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
12873
12873
|
segment = `:${segment.slice(1, -1)}`;
|
|
12874
12874
|
}
|
|
12875
|
-
walkApiRoutes(
|
|
12875
|
+
walkApiRoutes(path32.join(dir, entry.name), `${prefix}/${segment}`, cwd, out);
|
|
12876
12876
|
}
|
|
12877
12877
|
}
|
|
12878
12878
|
function scanEnvVars(cwd) {
|
|
12879
12879
|
const candidates = [".env.example", ".env.local.example", ".env.template"];
|
|
12880
12880
|
for (const envFile of candidates) {
|
|
12881
|
-
const envPath =
|
|
12882
|
-
if (!
|
|
12881
|
+
const envPath = path32.join(cwd, envFile);
|
|
12882
|
+
if (!fs34.existsSync(envPath)) continue;
|
|
12883
12883
|
try {
|
|
12884
|
-
const content =
|
|
12884
|
+
const content = fs34.readFileSync(envPath, "utf-8");
|
|
12885
12885
|
const vars = [];
|
|
12886
12886
|
for (const line of content.split("\n")) {
|
|
12887
12887
|
const trimmed = line.trim();
|
|
@@ -12926,8 +12926,8 @@ var init_frameworkDetectors = __esm({
|
|
|
12926
12926
|
});
|
|
12927
12927
|
|
|
12928
12928
|
// src/scripts/discoverQaContext.ts
|
|
12929
|
-
import * as
|
|
12930
|
-
import * as
|
|
12929
|
+
import * as fs35 from "fs";
|
|
12930
|
+
import * as path33 from "path";
|
|
12931
12931
|
function runQaDiscovery(cwd) {
|
|
12932
12932
|
const out = {
|
|
12933
12933
|
routes: [],
|
|
@@ -12958,9 +12958,9 @@ function runQaDiscovery(cwd) {
|
|
|
12958
12958
|
}
|
|
12959
12959
|
function detectDevServer(cwd, out) {
|
|
12960
12960
|
try {
|
|
12961
|
-
const pkg = JSON.parse(
|
|
12961
|
+
const pkg = JSON.parse(fs35.readFileSync(path33.join(cwd, "package.json"), "utf-8"));
|
|
12962
12962
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
12963
|
-
const pm =
|
|
12963
|
+
const pm = fs35.existsSync(path33.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs35.existsSync(path33.join(cwd, "yarn.lock")) ? "yarn" : fs35.existsSync(path33.join(cwd, "bun.lockb")) ? "bun" : "npm";
|
|
12964
12964
|
if (pkg.scripts?.dev) out.devCommand = `${pm} dev`;
|
|
12965
12965
|
if (allDeps.next || allDeps.nuxt) out.devPort = 3e3;
|
|
12966
12966
|
else if (allDeps.vite) out.devPort = 5173;
|
|
@@ -12970,8 +12970,8 @@ function detectDevServer(cwd, out) {
|
|
|
12970
12970
|
function scanFrontendRoutes(cwd, out) {
|
|
12971
12971
|
const appDirs = ["src/app", "app"];
|
|
12972
12972
|
for (const appDir of appDirs) {
|
|
12973
|
-
const full =
|
|
12974
|
-
if (!
|
|
12973
|
+
const full = path33.join(cwd, appDir);
|
|
12974
|
+
if (!fs35.existsSync(full)) continue;
|
|
12975
12975
|
walkFrontendRoutes(full, "", out);
|
|
12976
12976
|
break;
|
|
12977
12977
|
}
|
|
@@ -12979,7 +12979,7 @@ function scanFrontendRoutes(cwd, out) {
|
|
|
12979
12979
|
function walkFrontendRoutes(dir, prefix, out) {
|
|
12980
12980
|
let entries;
|
|
12981
12981
|
try {
|
|
12982
|
-
entries =
|
|
12982
|
+
entries = fs35.readdirSync(dir, { withFileTypes: true });
|
|
12983
12983
|
} catch {
|
|
12984
12984
|
return;
|
|
12985
12985
|
}
|
|
@@ -12996,7 +12996,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
12996
12996
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
12997
12997
|
let segment = entry.name;
|
|
12998
12998
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
12999
|
-
walkFrontendRoutes(
|
|
12999
|
+
walkFrontendRoutes(path33.join(dir, entry.name), prefix, out);
|
|
13000
13000
|
continue;
|
|
13001
13001
|
}
|
|
13002
13002
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -13004,7 +13004,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
13004
13004
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
13005
13005
|
segment = `:${segment.slice(1, -1)}`;
|
|
13006
13006
|
}
|
|
13007
|
-
walkFrontendRoutes(
|
|
13007
|
+
walkFrontendRoutes(path33.join(dir, entry.name), `${prefix}/${segment}`, out);
|
|
13008
13008
|
}
|
|
13009
13009
|
}
|
|
13010
13010
|
function detectAuthFiles(cwd, out) {
|
|
@@ -13021,23 +13021,23 @@ function detectAuthFiles(cwd, out) {
|
|
|
13021
13021
|
"src/app/api/oauth"
|
|
13022
13022
|
];
|
|
13023
13023
|
for (const c of candidates) {
|
|
13024
|
-
if (
|
|
13024
|
+
if (fs35.existsSync(path33.join(cwd, c))) out.authFiles.push(c);
|
|
13025
13025
|
}
|
|
13026
13026
|
}
|
|
13027
13027
|
function detectRoles(cwd, out) {
|
|
13028
13028
|
const rolePaths = ["src/types", "src/lib", "src/utils", "src/constants", "src/access", "src/collections"];
|
|
13029
13029
|
for (const rp of rolePaths) {
|
|
13030
|
-
const dir =
|
|
13031
|
-
if (!
|
|
13030
|
+
const dir = path33.join(cwd, rp);
|
|
13031
|
+
if (!fs35.existsSync(dir)) continue;
|
|
13032
13032
|
let files;
|
|
13033
13033
|
try {
|
|
13034
|
-
files =
|
|
13034
|
+
files = fs35.readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
13035
13035
|
} catch {
|
|
13036
13036
|
continue;
|
|
13037
13037
|
}
|
|
13038
13038
|
for (const f of files) {
|
|
13039
13039
|
try {
|
|
13040
|
-
const content =
|
|
13040
|
+
const content = fs35.readFileSync(path33.join(dir, f), "utf-8").slice(0, 5e3);
|
|
13041
13041
|
const roleMatches = content.match(/(?:role|Role|ROLE)\s*[=:]\s*['"](\w+)['"]/g);
|
|
13042
13042
|
if (roleMatches) {
|
|
13043
13043
|
for (const m of roleMatches) {
|
|
@@ -13524,7 +13524,7 @@ var init_triggerDispatcher = __esm({
|
|
|
13524
13524
|
});
|
|
13525
13525
|
|
|
13526
13526
|
// src/goal/policyResolver.ts
|
|
13527
|
-
import { createHash as
|
|
13527
|
+
import { createHash as createHash5 } from "crypto";
|
|
13528
13528
|
function resolveDispatchPolicy(input) {
|
|
13529
13529
|
const operation = input.catalog.operations.get(input.owner.definition.operationId);
|
|
13530
13530
|
if (!operation) throw new Error(`Dispatch blocked: Operation "${input.owner.definition.operationId}" is unresolved`);
|
|
@@ -13542,7 +13542,7 @@ function resolveDispatchPolicy(input) {
|
|
|
13542
13542
|
const snapshotValue = { policy, constraints };
|
|
13543
13543
|
return {
|
|
13544
13544
|
snapshot: {
|
|
13545
|
-
hash:
|
|
13545
|
+
hash: createHash5("sha256").update(stableJson(snapshotValue)).digest("hex"),
|
|
13546
13546
|
...snapshotValue
|
|
13547
13547
|
},
|
|
13548
13548
|
operation,
|
|
@@ -14992,15 +14992,15 @@ var init_fixFlow = __esm({
|
|
|
14992
14992
|
});
|
|
14993
14993
|
|
|
14994
14994
|
// src/workflow-template.ts
|
|
14995
|
-
import * as
|
|
14996
|
-
import * as
|
|
14995
|
+
import * as fs36 from "fs";
|
|
14996
|
+
import * as path34 from "path";
|
|
14997
14997
|
import { fileURLToPath } from "url";
|
|
14998
14998
|
function loadKodyWorkflowTemplate() {
|
|
14999
|
-
const here =
|
|
15000
|
-
const candidates = [
|
|
15001
|
-
const source = candidates.find((candidate) =>
|
|
14999
|
+
const here = path34.dirname(fileURLToPath(import.meta.url));
|
|
15000
|
+
const candidates = [path34.resolve(here, "../templates/kody.yml"), path34.resolve(here, "../../templates/kody.yml")];
|
|
15001
|
+
const source = candidates.find((candidate) => fs36.existsSync(candidate));
|
|
15002
15002
|
if (!source) throw new Error(`Kody workflow template is missing: ${KODY_WORKFLOW_TEMPLATE_PATH}`);
|
|
15003
|
-
return
|
|
15003
|
+
return fs36.readFileSync(source, "utf8");
|
|
15004
15004
|
}
|
|
15005
15005
|
var KODY_WORKFLOW_TEMPLATE_PATH;
|
|
15006
15006
|
var init_workflow_template = __esm({
|
|
@@ -15012,12 +15012,12 @@ var init_workflow_template = __esm({
|
|
|
15012
15012
|
|
|
15013
15013
|
// src/scripts/initFlow.ts
|
|
15014
15014
|
import { execFileSync as execFileSync14 } from "child_process";
|
|
15015
|
-
import * as
|
|
15016
|
-
import * as
|
|
15015
|
+
import * as fs37 from "fs";
|
|
15016
|
+
import * as path35 from "path";
|
|
15017
15017
|
function detectPackageManager(cwd) {
|
|
15018
|
-
if (
|
|
15019
|
-
if (
|
|
15020
|
-
if (
|
|
15018
|
+
if (fs37.existsSync(path35.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
15019
|
+
if (fs37.existsSync(path35.join(cwd, "yarn.lock"))) return "yarn";
|
|
15020
|
+
if (fs37.existsSync(path35.join(cwd, "bun.lockb"))) return "bun";
|
|
15021
15021
|
return "npm";
|
|
15022
15022
|
}
|
|
15023
15023
|
function qualityCommandsFor(pm) {
|
|
@@ -15089,22 +15089,22 @@ function performInit(cwd, force) {
|
|
|
15089
15089
|
const pm = detectPackageManager(cwd);
|
|
15090
15090
|
const ownerRepo = detectOwnerRepo(cwd);
|
|
15091
15091
|
const defaultBranch = defaultBranchFromGit(cwd);
|
|
15092
|
-
const configPath =
|
|
15093
|
-
if (
|
|
15092
|
+
const configPath = path35.join(cwd, "kody.config.json");
|
|
15093
|
+
if (fs37.existsSync(configPath) && !force) {
|
|
15094
15094
|
skipped.push("kody.config.json");
|
|
15095
15095
|
} else {
|
|
15096
15096
|
const cfg = makeConfig(pm, ownerRepo, defaultBranch);
|
|
15097
|
-
|
|
15097
|
+
fs37.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
|
|
15098
15098
|
`);
|
|
15099
15099
|
wrote.push("kody.config.json");
|
|
15100
15100
|
}
|
|
15101
|
-
const workflowDir =
|
|
15102
|
-
const workflowPath =
|
|
15103
|
-
if (
|
|
15101
|
+
const workflowDir = path35.join(cwd, ".github", "workflows");
|
|
15102
|
+
const workflowPath = path35.join(workflowDir, "kody.yml");
|
|
15103
|
+
if (fs37.existsSync(workflowPath) && !force) {
|
|
15104
15104
|
skipped.push(".github/workflows/kody.yml");
|
|
15105
15105
|
} else {
|
|
15106
|
-
|
|
15107
|
-
|
|
15106
|
+
fs37.mkdirSync(workflowDir, { recursive: true });
|
|
15107
|
+
fs37.writeFileSync(workflowPath, loadKodyWorkflowTemplate());
|
|
15108
15108
|
wrote.push(".github/workflows/kody.yml");
|
|
15109
15109
|
}
|
|
15110
15110
|
for (const exe of listRuntimeProfilesForCwd(cwd)) {
|
|
@@ -15115,12 +15115,12 @@ function performInit(cwd, force) {
|
|
|
15115
15115
|
continue;
|
|
15116
15116
|
}
|
|
15117
15117
|
if (profile.kind !== "scheduled" || !profile.schedule) continue;
|
|
15118
|
-
const target =
|
|
15119
|
-
if (
|
|
15118
|
+
const target = path35.join(workflowDir, `kody-${exe.name}.yml`);
|
|
15119
|
+
if (fs37.existsSync(target) && !force) {
|
|
15120
15120
|
skipped.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
15121
15121
|
continue;
|
|
15122
15122
|
}
|
|
15123
|
-
|
|
15123
|
+
fs37.writeFileSync(target, renderScheduledWorkflow(exe.name, profile.schedule));
|
|
15124
15124
|
wrote.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
15125
15125
|
}
|
|
15126
15126
|
let labels;
|
|
@@ -15208,7 +15208,7 @@ Nothing to do. All files already present. (Use --force to overwrite.)
|
|
|
15208
15208
|
});
|
|
15209
15209
|
|
|
15210
15210
|
// src/scripts/loadAgentAdhoc.ts
|
|
15211
|
-
import * as
|
|
15211
|
+
import * as fs38 from "fs";
|
|
15212
15212
|
function resolveMessage(messageArg) {
|
|
15213
15213
|
const fromComment = readCommentBody();
|
|
15214
15214
|
if (fromComment) return stripDirective(fromComment);
|
|
@@ -15216,9 +15216,9 @@ function resolveMessage(messageArg) {
|
|
|
15216
15216
|
}
|
|
15217
15217
|
function readCommentBody() {
|
|
15218
15218
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
15219
|
-
if (!eventPath || !
|
|
15219
|
+
if (!eventPath || !fs38.existsSync(eventPath)) return "";
|
|
15220
15220
|
try {
|
|
15221
|
-
const event = JSON.parse(
|
|
15221
|
+
const event = JSON.parse(fs38.readFileSync(eventPath, "utf-8"));
|
|
15222
15222
|
return String(event.comment?.body ?? "");
|
|
15223
15223
|
} catch {
|
|
15224
15224
|
return "";
|
|
@@ -15272,10 +15272,10 @@ var init_loadAgentAdhoc = __esm({
|
|
|
15272
15272
|
throw new Error("loadAgentAdhoc: ctx.args.agent must be a non-empty slug");
|
|
15273
15273
|
}
|
|
15274
15274
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
15275
|
-
if (!
|
|
15275
|
+
if (!fs38.existsSync(agentPath)) {
|
|
15276
15276
|
throw new Error(`loadAgentAdhoc: agent identity not found: ${agentPath}`);
|
|
15277
15277
|
}
|
|
15278
|
-
const { title, body } = parseAgentFile(
|
|
15278
|
+
const { title, body } = parseAgentFile(fs38.readFileSync(agentPath, "utf-8"), agentSlug);
|
|
15279
15279
|
const message = resolveMessage(ctx.args.message);
|
|
15280
15280
|
if (!message) {
|
|
15281
15281
|
throw new Error(
|
|
@@ -15345,7 +15345,7 @@ var init_loadCapabilityState = __esm({
|
|
|
15345
15345
|
|
|
15346
15346
|
// src/companyIntent.ts
|
|
15347
15347
|
function isCompanyIntentId(value) {
|
|
15348
|
-
return
|
|
15348
|
+
return SLUG_RE2.test(value);
|
|
15349
15349
|
}
|
|
15350
15350
|
function normalizeCompanyIntent(path52, raw) {
|
|
15351
15351
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
@@ -15459,14 +15459,14 @@ function normalizeAutomationPolicy(raw) {
|
|
|
15459
15459
|
requiresHumanFor: stringArray2(raw?.requiresHumanFor)
|
|
15460
15460
|
};
|
|
15461
15461
|
}
|
|
15462
|
-
var
|
|
15462
|
+
var SLUG_RE2;
|
|
15463
15463
|
var init_companyIntent = __esm({
|
|
15464
15464
|
"src/companyIntent.ts"() {
|
|
15465
15465
|
"use strict";
|
|
15466
15466
|
init_state2();
|
|
15467
15467
|
init_stateStore();
|
|
15468
15468
|
init_state_backend();
|
|
15469
|
-
|
|
15469
|
+
SLUG_RE2 = /^[a-z][a-z0-9-]{0,63}$/;
|
|
15470
15470
|
}
|
|
15471
15471
|
});
|
|
15472
15472
|
|
|
@@ -15644,8 +15644,8 @@ var init_loadIssueStateComment = __esm({
|
|
|
15644
15644
|
});
|
|
15645
15645
|
|
|
15646
15646
|
// src/scripts/loadJobFromFile.ts
|
|
15647
|
-
import * as
|
|
15648
|
-
import * as
|
|
15647
|
+
import * as fs39 from "fs";
|
|
15648
|
+
import * as path36 from "path";
|
|
15649
15649
|
function parseJobFile(raw, slug) {
|
|
15650
15650
|
let stripped = raw;
|
|
15651
15651
|
if (stripped.startsWith("---\n")) {
|
|
@@ -15684,10 +15684,10 @@ var init_loadJobFromFile = __esm({
|
|
|
15684
15684
|
if (!slug) {
|
|
15685
15685
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
15686
15686
|
}
|
|
15687
|
-
const capability = resolveCapabilityFolder(slug,
|
|
15687
|
+
const capability = resolveCapabilityFolder(slug, path36.resolve(ctx.cwd, jobsDir));
|
|
15688
15688
|
if (!capability) {
|
|
15689
15689
|
throw new Error(
|
|
15690
|
-
`loadJobFromFile: capability folder not found or incomplete: ${
|
|
15690
|
+
`loadJobFromFile: capability folder not found or incomplete: ${path36.resolve(ctx.cwd, jobsDir, slug)}`
|
|
15691
15691
|
);
|
|
15692
15692
|
}
|
|
15693
15693
|
const { title, body, config } = capability;
|
|
@@ -15697,12 +15697,12 @@ var init_loadJobFromFile = __esm({
|
|
|
15697
15697
|
let agentIdentity = "";
|
|
15698
15698
|
if (agentSlug) {
|
|
15699
15699
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
15700
|
-
if (!
|
|
15700
|
+
if (!fs39.existsSync(agentPath)) {
|
|
15701
15701
|
throw new Error(
|
|
15702
15702
|
`loadJobFromFile: capability '${slug}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
15703
15703
|
);
|
|
15704
15704
|
}
|
|
15705
|
-
const agentRaw =
|
|
15705
|
+
const agentRaw = fs39.readFileSync(agentPath, "utf-8");
|
|
15706
15706
|
const parsed = parseJobFile(agentRaw, agentSlug);
|
|
15707
15707
|
agentTitle = parsed.title;
|
|
15708
15708
|
agentIdentity = parsed.body;
|
|
@@ -15782,13 +15782,13 @@ ${truncate2(issue2.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
15782
15782
|
});
|
|
15783
15783
|
|
|
15784
15784
|
// src/scripts/kodyVariables.ts
|
|
15785
|
-
import * as
|
|
15786
|
-
import * as
|
|
15785
|
+
import * as fs40 from "fs";
|
|
15786
|
+
import * as path37 from "path";
|
|
15787
15787
|
function readKodyVariables(cwd) {
|
|
15788
|
-
const full =
|
|
15788
|
+
const full = path37.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
15789
15789
|
let raw;
|
|
15790
15790
|
try {
|
|
15791
|
-
raw =
|
|
15791
|
+
raw = fs40.readFileSync(full, "utf-8");
|
|
15792
15792
|
} catch {
|
|
15793
15793
|
return {};
|
|
15794
15794
|
}
|
|
@@ -15813,9 +15813,9 @@ var init_kodyVariables = __esm({
|
|
|
15813
15813
|
});
|
|
15814
15814
|
|
|
15815
15815
|
// src/backendVault.ts
|
|
15816
|
-
import { createDecipheriv, createHash as
|
|
15816
|
+
import { createDecipheriv, createHash as createHash6 } from "crypto";
|
|
15817
15817
|
function cacheKey(owner, repo, masterKey) {
|
|
15818
|
-
const keyHash =
|
|
15818
|
+
const keyHash = createHash6("sha256").update(masterKey).digest("hex").slice(0, 16);
|
|
15819
15819
|
return `${owner}/${repo}:${keyHash}`.toLowerCase();
|
|
15820
15820
|
}
|
|
15821
15821
|
function decryptVault(payload, masterKey) {
|
|
@@ -15964,8 +15964,8 @@ var init_runtimeSecrets = __esm({
|
|
|
15964
15964
|
});
|
|
15965
15965
|
|
|
15966
15966
|
// src/scripts/loadQaContext.ts
|
|
15967
|
-
import * as
|
|
15968
|
-
import * as
|
|
15967
|
+
import * as fs41 from "fs";
|
|
15968
|
+
import * as path38 from "path";
|
|
15969
15969
|
function parseSlugList(value) {
|
|
15970
15970
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
15971
15971
|
return inner.split(",").map(
|
|
@@ -15994,18 +15994,18 @@ function readProfileAgents(raw) {
|
|
|
15994
15994
|
return { agent: agent ?? legacy ?? ["kody"], body };
|
|
15995
15995
|
}
|
|
15996
15996
|
function readProfile(cwd) {
|
|
15997
|
-
const dir =
|
|
15998
|
-
if (!
|
|
15997
|
+
const dir = path38.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
15998
|
+
if (!fs41.existsSync(dir)) return "";
|
|
15999
15999
|
let entries;
|
|
16000
16000
|
try {
|
|
16001
|
-
entries =
|
|
16001
|
+
entries = fs41.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
16002
16002
|
} catch {
|
|
16003
16003
|
return "";
|
|
16004
16004
|
}
|
|
16005
16005
|
const blocks = [];
|
|
16006
16006
|
for (const file of entries) {
|
|
16007
16007
|
try {
|
|
16008
|
-
const raw =
|
|
16008
|
+
const raw = fs41.readFileSync(path38.join(dir, file), "utf-8");
|
|
16009
16009
|
const { agent, body } = readProfileAgents(raw);
|
|
16010
16010
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
16011
16011
|
blocks.push(`## ${file}
|
|
@@ -16054,8 +16054,8 @@ var init_loadQaContext = __esm({
|
|
|
16054
16054
|
});
|
|
16055
16055
|
|
|
16056
16056
|
// src/taskContext.ts
|
|
16057
|
-
import * as
|
|
16058
|
-
import * as
|
|
16057
|
+
import * as fs42 from "fs";
|
|
16058
|
+
import * as path39 from "path";
|
|
16059
16059
|
function buildTaskContext(args) {
|
|
16060
16060
|
return {
|
|
16061
16061
|
schemaVersion: TASK_CONTEXT_SCHEMA_VERSION,
|
|
@@ -16071,9 +16071,9 @@ function buildTaskContext(args) {
|
|
|
16071
16071
|
function persistTaskContext(cwd, ctx) {
|
|
16072
16072
|
try {
|
|
16073
16073
|
const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
|
|
16074
|
-
|
|
16075
|
-
const file =
|
|
16076
|
-
|
|
16074
|
+
fs42.mkdirSync(dir, { recursive: true });
|
|
16075
|
+
const file = path39.join(dir, "task-context.json");
|
|
16076
|
+
fs42.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
|
|
16077
16077
|
`);
|
|
16078
16078
|
return file;
|
|
16079
16079
|
} catch (err) {
|
|
@@ -16464,7 +16464,7 @@ var init_notifyTerminal = __esm({
|
|
|
16464
16464
|
});
|
|
16465
16465
|
|
|
16466
16466
|
// src/scripts/openAgencyModelReviewPr.ts
|
|
16467
|
-
import { createHash as
|
|
16467
|
+
import { createHash as createHash7 } from "crypto";
|
|
16468
16468
|
function parseAgencyModelProposal(raw) {
|
|
16469
16469
|
const text2 = raw.trim();
|
|
16470
16470
|
const jsonText = (text2.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/i)?.[1] ?? text2).trim();
|
|
@@ -16516,7 +16516,7 @@ function normalizeBundleFiles(bundle) {
|
|
|
16516
16516
|
});
|
|
16517
16517
|
}
|
|
16518
16518
|
function buildProposalId(issueNumber, bundle, sourceLabel) {
|
|
16519
|
-
const digest =
|
|
16519
|
+
const digest = createHash7("sha256").update(JSON.stringify({ issueNumber, sourceLabel, title: bundle.title, files: normalizeBundleFiles(bundle) })).digest("hex").slice(0, 16);
|
|
16520
16520
|
return `issue-${issueNumber}-${digest}`;
|
|
16521
16521
|
}
|
|
16522
16522
|
function isDryRun(ctx) {
|
|
@@ -17456,9 +17456,9 @@ var init_postResearchComment = __esm({
|
|
|
17456
17456
|
});
|
|
17457
17457
|
|
|
17458
17458
|
// src/scripts/prepareBrowserAuth.ts
|
|
17459
|
-
import * as
|
|
17459
|
+
import * as fs43 from "fs";
|
|
17460
17460
|
import * as os6 from "os";
|
|
17461
|
-
import * as
|
|
17461
|
+
import * as path40 from "path";
|
|
17462
17462
|
function appendAuthMessage(ctx, message) {
|
|
17463
17463
|
const current = typeof ctx.data.qaAuthBlock === "string" ? ctx.data.qaAuthBlock.trim() : "";
|
|
17464
17464
|
ctx.data.qaAuthBlock = current ? `${current}
|
|
@@ -17497,9 +17497,9 @@ async function githubJson(url, token) {
|
|
|
17497
17497
|
return await response.json();
|
|
17498
17498
|
}
|
|
17499
17499
|
function writeKodyStorageState(input) {
|
|
17500
|
-
const directory =
|
|
17501
|
-
|
|
17502
|
-
const file =
|
|
17500
|
+
const directory = fs43.mkdtempSync(path40.join(os6.tmpdir(), "kody-browser-auth-"));
|
|
17501
|
+
fs43.chmodSync(directory, 448);
|
|
17502
|
+
const file = path40.join(directory, "storage-state.json");
|
|
17503
17503
|
const now = Date.now();
|
|
17504
17504
|
const repoEntry = {
|
|
17505
17505
|
repoUrl: input.repoUrl,
|
|
@@ -17529,7 +17529,7 @@ function writeKodyStorageState(input) {
|
|
|
17529
17529
|
}
|
|
17530
17530
|
]
|
|
17531
17531
|
};
|
|
17532
|
-
|
|
17532
|
+
fs43.writeFileSync(file, JSON.stringify(storageState), { mode: 384 });
|
|
17533
17533
|
return { directory, file };
|
|
17534
17534
|
}
|
|
17535
17535
|
function configurePlaywright(profile, storageStatePath) {
|
|
@@ -17611,7 +17611,7 @@ async function prepareMethod(ctx, profile, method) {
|
|
|
17611
17611
|
configurePlaywright(profile, state.file);
|
|
17612
17612
|
const authDirectory = state.directory;
|
|
17613
17613
|
registerRuntimeCleanup(ctx, () => {
|
|
17614
|
-
|
|
17614
|
+
fs43.rmSync(authDirectory, { recursive: true, force: true });
|
|
17615
17615
|
});
|
|
17616
17616
|
appendAuthMessage(
|
|
17617
17617
|
ctx,
|
|
@@ -17619,7 +17619,7 @@ async function prepareMethod(ctx, profile, method) {
|
|
|
17619
17619
|
);
|
|
17620
17620
|
return true;
|
|
17621
17621
|
} catch (error) {
|
|
17622
|
-
if (state)
|
|
17622
|
+
if (state) fs43.rmSync(state.directory, { recursive: true, force: true });
|
|
17623
17623
|
const reason = error instanceof Error ? error.message : String(error);
|
|
17624
17624
|
appendAuthMessage(
|
|
17625
17625
|
ctx,
|
|
@@ -18588,9 +18588,9 @@ var init_runFlow = __esm({
|
|
|
18588
18588
|
});
|
|
18589
18589
|
|
|
18590
18590
|
// src/scripts/previewBuildHelpers.ts
|
|
18591
|
-
import { createDecipheriv as createDecipheriv2, createHash as
|
|
18591
|
+
import { createDecipheriv as createDecipheriv2, createHash as createHash8, hkdfSync as hkdfSync2 } from "crypto";
|
|
18592
18592
|
function shortHash(s) {
|
|
18593
|
-
return
|
|
18593
|
+
return createHash8("sha256").update(s).digest("hex").slice(0, 6);
|
|
18594
18594
|
}
|
|
18595
18595
|
function previewAppName(repo, pr) {
|
|
18596
18596
|
const [owner, name] = repo.split("/");
|
|
@@ -18623,7 +18623,7 @@ function formatPreviewComment(args) {
|
|
|
18623
18623
|
].join("\n");
|
|
18624
18624
|
}
|
|
18625
18625
|
function defaultImageTag(repo, ref) {
|
|
18626
|
-
return
|
|
18626
|
+
return createHash8("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
|
|
18627
18627
|
}
|
|
18628
18628
|
var init_previewBuildHelpers = __esm({
|
|
18629
18629
|
"src/scripts/previewBuildHelpers.ts"() {
|
|
@@ -18718,12 +18718,12 @@ fi
|
|
|
18718
18718
|
|
|
18719
18719
|
// src/scripts/runPreviewBuild.ts
|
|
18720
18720
|
import { copyFile, writeFile } from "fs/promises";
|
|
18721
|
-
import * as
|
|
18721
|
+
import * as path41 from "path";
|
|
18722
18722
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
18723
18723
|
function bundledDockerfilePath(mode) {
|
|
18724
|
-
const here =
|
|
18724
|
+
const here = path41.dirname(fileURLToPath2(import.meta.url));
|
|
18725
18725
|
const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
|
|
18726
|
-
return
|
|
18726
|
+
return path41.join(here, "preview-build-templates", file);
|
|
18727
18727
|
}
|
|
18728
18728
|
function required(name) {
|
|
18729
18729
|
const v = (process.env[name] ?? "").trim();
|
|
@@ -18958,10 +18958,10 @@ var init_runPreviewBuild = __esm({
|
|
|
18958
18958
|
console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
|
|
18959
18959
|
if (Object.keys(buildEnv).length > 0) {
|
|
18960
18960
|
const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
|
|
18961
|
-
await writeFile(
|
|
18961
|
+
await writeFile(path41.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
|
|
18962
18962
|
`, "utf8");
|
|
18963
18963
|
}
|
|
18964
|
-
const consumerDockerfile =
|
|
18964
|
+
const consumerDockerfile = path41.join(ctx.cwd, "Dockerfile.preview");
|
|
18965
18965
|
const { stat } = await import("fs/promises");
|
|
18966
18966
|
let hasConsumerDockerfile = false;
|
|
18967
18967
|
try {
|
|
@@ -19145,8 +19145,8 @@ var init_tickShellRunner = __esm({
|
|
|
19145
19145
|
});
|
|
19146
19146
|
|
|
19147
19147
|
// src/scripts/runScheduledImplementationTick.ts
|
|
19148
|
-
import * as
|
|
19149
|
-
import * as
|
|
19148
|
+
import * as fs44 from "fs";
|
|
19149
|
+
import * as path42 from "path";
|
|
19150
19150
|
var runScheduledImplementationTick;
|
|
19151
19151
|
var init_runScheduledImplementationTick = __esm({
|
|
19152
19152
|
"src/scripts/runScheduledImplementationTick.ts"() {
|
|
@@ -19167,14 +19167,14 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
19167
19167
|
ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
19168
19168
|
return;
|
|
19169
19169
|
}
|
|
19170
|
-
const capability = resolveCapabilityFolder(slug,
|
|
19170
|
+
const capability = resolveCapabilityFolder(slug, path42.resolve(ctx.cwd, jobsDir));
|
|
19171
19171
|
if (!capability) {
|
|
19172
19172
|
ctx.output.exitCode = 99;
|
|
19173
19173
|
ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug} (searched ${jobsDir} and company store)`;
|
|
19174
19174
|
return;
|
|
19175
19175
|
}
|
|
19176
|
-
const shellPath =
|
|
19177
|
-
if (!
|
|
19176
|
+
const shellPath = path42.join(profile.dir, shell);
|
|
19177
|
+
if (!fs44.existsSync(shellPath)) {
|
|
19178
19178
|
ctx.output.exitCode = 99;
|
|
19179
19179
|
ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
19180
19180
|
return;
|
|
@@ -19205,8 +19205,8 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
19205
19205
|
});
|
|
19206
19206
|
|
|
19207
19207
|
// src/scripts/runTickScript.ts
|
|
19208
|
-
import * as
|
|
19209
|
-
import * as
|
|
19208
|
+
import * as fs45 from "fs";
|
|
19209
|
+
import * as path43 from "path";
|
|
19210
19210
|
var runTickScript;
|
|
19211
19211
|
var init_runTickScript = __esm({
|
|
19212
19212
|
"src/scripts/runTickScript.ts"() {
|
|
@@ -19226,10 +19226,10 @@ var init_runTickScript = __esm({
|
|
|
19226
19226
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
19227
19227
|
return;
|
|
19228
19228
|
}
|
|
19229
|
-
const capability = readCapabilityFolder(
|
|
19229
|
+
const capability = readCapabilityFolder(path43.resolve(ctx.cwd, jobsDir), slug);
|
|
19230
19230
|
if (!capability) {
|
|
19231
19231
|
ctx.output.exitCode = 99;
|
|
19232
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${
|
|
19232
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path43.resolve(ctx.cwd, jobsDir, slug)}`;
|
|
19233
19233
|
return;
|
|
19234
19234
|
}
|
|
19235
19235
|
const tickScript = capability.config.tickScript;
|
|
@@ -19238,8 +19238,8 @@ var init_runTickScript = __esm({
|
|
|
19238
19238
|
ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
19239
19239
|
return;
|
|
19240
19240
|
}
|
|
19241
|
-
const scriptPath =
|
|
19242
|
-
if (!
|
|
19241
|
+
const scriptPath = path43.isAbsolute(tickScript) ? tickScript : path43.join(ctx.cwd, tickScript);
|
|
19242
|
+
if (!fs45.existsSync(scriptPath)) {
|
|
19243
19243
|
ctx.output.exitCode = 99;
|
|
19244
19244
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
19245
19245
|
return;
|
|
@@ -19521,7 +19521,7 @@ var init_syncFlow = __esm({
|
|
|
19521
19521
|
});
|
|
19522
19522
|
|
|
19523
19523
|
// src/scripts/validateAgencyModelProposal.ts
|
|
19524
|
-
import * as
|
|
19524
|
+
import * as path44 from "path";
|
|
19525
19525
|
function validateModelBundle(bundle, expectedKind, options = {}) {
|
|
19526
19526
|
const failures = [];
|
|
19527
19527
|
validateOneModel(bundle.model, bundle.files, "model", true, failures, expectedKind, options);
|
|
@@ -19847,7 +19847,7 @@ var init_validateAgencyModelProposal = __esm({
|
|
|
19847
19847
|
const bundle = parseAgencyModelProposal(raw);
|
|
19848
19848
|
const expectedKind = readExpectedModelKind(args);
|
|
19849
19849
|
const failures = validateModelBundle(bundle, expectedKind, {
|
|
19850
|
-
capabilityRoot:
|
|
19850
|
+
capabilityRoot: path44.join(ctx.cwd, ".kody", "capabilities")
|
|
19851
19851
|
});
|
|
19852
19852
|
if (failures.length > 0) {
|
|
19853
19853
|
throw new Error(`validateAgencyModelProposal: ${failures.join("; ")}`);
|
|
@@ -20398,7 +20398,7 @@ var init_warmupMcp = __esm({
|
|
|
20398
20398
|
});
|
|
20399
20399
|
|
|
20400
20400
|
// src/scripts/writeAgentRunSummary.ts
|
|
20401
|
-
import * as
|
|
20401
|
+
import * as fs46 from "fs";
|
|
20402
20402
|
var writeAgentRunSummary;
|
|
20403
20403
|
var init_writeAgentRunSummary = __esm({
|
|
20404
20404
|
"src/scripts/writeAgentRunSummary.ts"() {
|
|
@@ -20424,7 +20424,7 @@ var init_writeAgentRunSummary = __esm({
|
|
|
20424
20424
|
if (reason) lines.push(`- **Reason:** ${reason}`);
|
|
20425
20425
|
lines.push("");
|
|
20426
20426
|
try {
|
|
20427
|
-
|
|
20427
|
+
fs46.appendFileSync(summaryPath, `${lines.join("\n")}
|
|
20428
20428
|
`);
|
|
20429
20429
|
} catch {
|
|
20430
20430
|
}
|
|
@@ -20752,17 +20752,17 @@ var init_scripts = __esm({
|
|
|
20752
20752
|
});
|
|
20753
20753
|
|
|
20754
20754
|
// src/stateWorkspace.ts
|
|
20755
|
-
import * as
|
|
20756
|
-
import * as
|
|
20755
|
+
import * as fs47 from "fs";
|
|
20756
|
+
import * as path45 from "path";
|
|
20757
20757
|
function tenantId(config) {
|
|
20758
20758
|
const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
|
|
20759
20759
|
const repo = config.github?.repo?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
|
|
20760
20760
|
return owner && repo ? `${owner}/${repo}` : null;
|
|
20761
20761
|
}
|
|
20762
20762
|
function writeRuntimeFile(cwd, relativePath, content) {
|
|
20763
|
-
const target =
|
|
20764
|
-
|
|
20765
|
-
|
|
20763
|
+
const target = path45.join(cwd, RUNTIME_ROOT, relativePath);
|
|
20764
|
+
fs47.mkdirSync(path45.dirname(target), { recursive: true });
|
|
20765
|
+
fs47.writeFileSync(target, content, "utf8");
|
|
20766
20766
|
}
|
|
20767
20767
|
function record(value) {
|
|
20768
20768
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -20827,11 +20827,11 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
|
|
|
20827
20827
|
throw new Error("Kody backend access is required for runtime workspace documents");
|
|
20828
20828
|
return;
|
|
20829
20829
|
}
|
|
20830
|
-
const key = `${
|
|
20830
|
+
const key = `${path45.resolve(cwd)}|${tenant}`;
|
|
20831
20831
|
if (hydratedWorkspaces.has(key)) return;
|
|
20832
20832
|
const backend = backendOverride ?? createStateBackendFromEnv();
|
|
20833
|
-
const root =
|
|
20834
|
-
|
|
20833
|
+
const root = path45.join(cwd, RUNTIME_ROOT);
|
|
20834
|
+
fs47.rmSync(root, { recursive: true, force: true });
|
|
20835
20835
|
await Promise.all([
|
|
20836
20836
|
hydratePrefix(backend, tenant, cwd, "context:"),
|
|
20837
20837
|
hydratePrefix(backend, tenant, cwd, "memory:"),
|
|
@@ -20847,7 +20847,7 @@ var init_stateWorkspace = __esm({
|
|
|
20847
20847
|
"src/stateWorkspace.ts"() {
|
|
20848
20848
|
"use strict";
|
|
20849
20849
|
init_state_backend();
|
|
20850
|
-
RUNTIME_ROOT =
|
|
20850
|
+
RUNTIME_ROOT = path45.join(".kody-engine", "runtime");
|
|
20851
20851
|
hydratedWorkspaces = /* @__PURE__ */ new Set();
|
|
20852
20852
|
}
|
|
20853
20853
|
});
|
|
@@ -20918,9 +20918,9 @@ var init_tools = __esm({
|
|
|
20918
20918
|
|
|
20919
20919
|
// src/executor.ts
|
|
20920
20920
|
import { spawn as spawn8 } from "child_process";
|
|
20921
|
-
import * as
|
|
20921
|
+
import * as fs48 from "fs";
|
|
20922
20922
|
import * as os7 from "os";
|
|
20923
|
-
import * as
|
|
20923
|
+
import * as path46 from "path";
|
|
20924
20924
|
function isMutatingPostflight(scriptName) {
|
|
20925
20925
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
20926
20926
|
}
|
|
@@ -21161,7 +21161,7 @@ async function runImplementation(profileName, input) {
|
|
|
21161
21161
|
const jobWhyBlock = typeof ctx.data.jobWhy === "string" ? operatorRequestBlock(ctx.data.jobWhy) : null;
|
|
21162
21162
|
const jobRefBlock = jobReferenceBlock(profileName, profile, ctx.data);
|
|
21163
21163
|
const invokeAgent = async (prompt) => {
|
|
21164
|
-
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) =>
|
|
21164
|
+
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path46.isAbsolute(p) ? p : path46.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
21165
21165
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
21166
21166
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
21167
21167
|
const agents = loadSubagents(profile);
|
|
@@ -21623,17 +21623,17 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
21623
21623
|
function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
21624
21624
|
const found = resolveImplementation(profileName, getRuntimeProfileRootsForCwd(cwd));
|
|
21625
21625
|
if (found) return found;
|
|
21626
|
-
const here =
|
|
21626
|
+
const here = path46.dirname(new URL(import.meta.url).pathname);
|
|
21627
21627
|
const candidates = [
|
|
21628
|
-
|
|
21628
|
+
path46.join(here, "implementations", profileName, "profile.json"),
|
|
21629
21629
|
// same-dir sibling (dev)
|
|
21630
|
-
|
|
21630
|
+
path46.join(here, "..", "implementations", profileName, "profile.json"),
|
|
21631
21631
|
// up one (prod: dist/bin → dist/implementations)
|
|
21632
|
-
|
|
21632
|
+
path46.join(here, "..", "src", "implementations", profileName, "profile.json")
|
|
21633
21633
|
// fallback
|
|
21634
21634
|
];
|
|
21635
21635
|
for (const c of candidates) {
|
|
21636
|
-
if (
|
|
21636
|
+
if (fs48.existsSync(c)) return c;
|
|
21637
21637
|
}
|
|
21638
21638
|
return candidates[0];
|
|
21639
21639
|
}
|
|
@@ -21748,15 +21748,15 @@ function resolveShellTimeoutMs(entry) {
|
|
|
21748
21748
|
}
|
|
21749
21749
|
async function runShellEntry(entry, ctx, profile) {
|
|
21750
21750
|
const shellName = entry.shell;
|
|
21751
|
-
const shellPath =
|
|
21752
|
-
if (!
|
|
21751
|
+
const shellPath = path46.join(profile.dir, shellName);
|
|
21752
|
+
if (!fs48.existsSync(shellPath)) {
|
|
21753
21753
|
ctx.skipAgent = true;
|
|
21754
21754
|
ctx.output.exitCode = 99;
|
|
21755
21755
|
ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
|
|
21756
21756
|
return;
|
|
21757
21757
|
}
|
|
21758
21758
|
const positional = entry.with ? Object.values(entry.with).map((v) => String(v)) : [];
|
|
21759
|
-
const outputFile =
|
|
21759
|
+
const outputFile = path46.join(
|
|
21760
21760
|
os7.tmpdir(),
|
|
21761
21761
|
`kody-shell-output-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
21762
21762
|
);
|
|
@@ -21828,9 +21828,9 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
21828
21828
|
}
|
|
21829
21829
|
let sideChannelText = "";
|
|
21830
21830
|
try {
|
|
21831
|
-
if (
|
|
21832
|
-
sideChannelText =
|
|
21833
|
-
|
|
21831
|
+
if (fs48.existsSync(outputFile)) {
|
|
21832
|
+
sideChannelText = fs48.readFileSync(outputFile, "utf-8");
|
|
21833
|
+
fs48.rmSync(outputFile, { force: true });
|
|
21834
21834
|
}
|
|
21835
21835
|
} catch {
|
|
21836
21836
|
}
|
|
@@ -22002,7 +22002,7 @@ __export(job_exports, {
|
|
|
22002
22002
|
stableJobKey: () => stableJobKey,
|
|
22003
22003
|
validateJob: () => validateJob
|
|
22004
22004
|
});
|
|
22005
|
-
import * as
|
|
22005
|
+
import * as path47 from "path";
|
|
22006
22006
|
function newJobId(flavor) {
|
|
22007
22007
|
localJobSeq += 1;
|
|
22008
22008
|
const runId = process.env.GITHUB_RUN_ID;
|
|
@@ -22679,7 +22679,7 @@ function loadCapabilityContext(slug, cwd) {
|
|
|
22679
22679
|
return resolveCapabilityFolder(slug, hydratedCapabilitiesRoot(cwd));
|
|
22680
22680
|
}
|
|
22681
22681
|
function hydratedCapabilitiesRoot(cwd) {
|
|
22682
|
-
return
|
|
22682
|
+
return path47.join(cwd, ".kody-engine", "definitions", "capabilities");
|
|
22683
22683
|
}
|
|
22684
22684
|
function loadWorkflowContext(slug, base) {
|
|
22685
22685
|
if (!slug || !isWorkflowDefinitionId(slug)) return null;
|
|
@@ -22844,7 +22844,7 @@ function translateOpenAISseToBrain(opts) {
|
|
|
22844
22844
|
|
|
22845
22845
|
// src/servers/brain-serve.ts
|
|
22846
22846
|
import { createServer as createServer2 } from "http";
|
|
22847
|
-
import * as
|
|
22847
|
+
import * as path50 from "path";
|
|
22848
22848
|
|
|
22849
22849
|
// src/chat/loop.ts
|
|
22850
22850
|
init_agent();
|
|
@@ -23884,10 +23884,142 @@ function readSession(file) {
|
|
|
23884
23884
|
// src/servers/brain-serve.ts
|
|
23885
23885
|
init_config();
|
|
23886
23886
|
|
|
23887
|
+
// src/definition-hydration.ts
|
|
23888
|
+
init_state_backend();
|
|
23889
|
+
import { createHash as createHash3 } from "crypto";
|
|
23890
|
+
import * as fs16 from "fs";
|
|
23891
|
+
import * as path17 from "path";
|
|
23892
|
+
var SLUG_RE = /^[a-z0-9][a-z0-9_-]{0,127}$/;
|
|
23893
|
+
function assertSafeDefinitionPath(filePath) {
|
|
23894
|
+
const segments = filePath.split("/");
|
|
23895
|
+
if (!filePath || filePath.startsWith("/") || filePath.includes("\\") || filePath.includes("\0") || segments.some((segment) => !segment || segment === "." || segment === "..")) {
|
|
23896
|
+
throw new Error(`unsafe definition path: ${filePath}`);
|
|
23897
|
+
}
|
|
23898
|
+
}
|
|
23899
|
+
function normalizeDefinitionBundle(bundle) {
|
|
23900
|
+
if (bundle.schemaVersion !== 1) throw new Error("unsupported definition bundle schema");
|
|
23901
|
+
const files = Object.fromEntries(
|
|
23902
|
+
Object.entries(bundle.files).sort(([left], [right]) => left.localeCompare(right)).map(([filePath, content]) => {
|
|
23903
|
+
assertSafeDefinitionPath(filePath);
|
|
23904
|
+
return [filePath, content.replace(/\r\n?/g, "\n")];
|
|
23905
|
+
})
|
|
23906
|
+
);
|
|
23907
|
+
return { schemaVersion: 1, files };
|
|
23908
|
+
}
|
|
23909
|
+
function definitionVersion(bundle) {
|
|
23910
|
+
return `sha256:${createHash3("sha256").update(JSON.stringify(normalizeDefinitionBundle(bundle))).digest("hex")}`;
|
|
23911
|
+
}
|
|
23912
|
+
function verifyDefinition(definition) {
|
|
23913
|
+
if (!SLUG_RE.test(definition.slug)) throw new Error(`invalid definition slug: ${definition.slug}`);
|
|
23914
|
+
const bundle = normalizeDefinitionBundle(definition.bundle);
|
|
23915
|
+
if (definitionVersion(bundle) !== definition.version) {
|
|
23916
|
+
throw new Error(`definition version mismatch for ${definition.slug}: ${definition.version}`);
|
|
23917
|
+
}
|
|
23918
|
+
return bundle;
|
|
23919
|
+
}
|
|
23920
|
+
function writeBundle(root, bundle) {
|
|
23921
|
+
for (const [filePath, contents] of Object.entries(bundle.files)) {
|
|
23922
|
+
const target = path17.join(root, filePath);
|
|
23923
|
+
fs16.mkdirSync(path17.dirname(target), { recursive: true });
|
|
23924
|
+
fs16.writeFileSync(target, contents, "utf8");
|
|
23925
|
+
}
|
|
23926
|
+
}
|
|
23927
|
+
function writeDefinition(root, kind, definition) {
|
|
23928
|
+
const bundle = verifyDefinition(definition);
|
|
23929
|
+
if (kind === "agent") {
|
|
23930
|
+
const raw = bundle.files["agent.md"];
|
|
23931
|
+
if (typeof raw !== "string") throw new Error(`agent definition ${definition.slug} is missing agent.md`);
|
|
23932
|
+
fs16.writeFileSync(path17.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
|
|
23933
|
+
return;
|
|
23934
|
+
}
|
|
23935
|
+
if (kind === "goal") {
|
|
23936
|
+
writeBundle(path17.join(root, "goals", definition.slug), bundle);
|
|
23937
|
+
return;
|
|
23938
|
+
}
|
|
23939
|
+
if (kind === "implementation") {
|
|
23940
|
+
writeBundle(path17.join(root, "implementations", definition.slug), bundle);
|
|
23941
|
+
return;
|
|
23942
|
+
}
|
|
23943
|
+
if (kind === "asset") {
|
|
23944
|
+
writeBundle(path17.join(root, "shared"), bundle);
|
|
23945
|
+
return;
|
|
23946
|
+
}
|
|
23947
|
+
writeBundle(path17.join(root, "capabilities", definition.slug), bundle);
|
|
23948
|
+
}
|
|
23949
|
+
async function hydrateDefinitions(options) {
|
|
23950
|
+
const root = path17.join(options.cwd, ".kody-engine", "definitions");
|
|
23951
|
+
const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
|
|
23952
|
+
fs16.rmSync(staging, { recursive: true, force: true });
|
|
23953
|
+
fs16.mkdirSync(path17.join(staging, "agents"), { recursive: true });
|
|
23954
|
+
fs16.mkdirSync(path17.join(staging, "capabilities"), { recursive: true });
|
|
23955
|
+
fs16.mkdirSync(path17.join(staging, "goals"), { recursive: true });
|
|
23956
|
+
fs16.mkdirSync(path17.join(staging, "implementations"), { recursive: true });
|
|
23957
|
+
fs16.mkdirSync(path17.join(staging, "shared"), { recursive: true });
|
|
23958
|
+
try {
|
|
23959
|
+
const [capabilities, agents, goals, implementations, assets] = await Promise.all([
|
|
23960
|
+
options.backend.listDefinitions(options.tenantId, "capability"),
|
|
23961
|
+
options.backend.listDefinitions(options.tenantId, "agent"),
|
|
23962
|
+
options.backend.listDefinitions(options.tenantId, "goal"),
|
|
23963
|
+
options.backend.listDefinitions(options.tenantId, "implementation"),
|
|
23964
|
+
options.backend.listDefinitions(options.tenantId, "asset")
|
|
23965
|
+
]);
|
|
23966
|
+
const versions = {};
|
|
23967
|
+
for (const definition of capabilities) {
|
|
23968
|
+
writeDefinition(staging, "capability", definition);
|
|
23969
|
+
versions[`capability:${definition.slug}`] = definition.version;
|
|
23970
|
+
}
|
|
23971
|
+
for (const definition of agents) {
|
|
23972
|
+
writeDefinition(staging, "agent", definition);
|
|
23973
|
+
versions[`agent:${definition.slug}`] = definition.version;
|
|
23974
|
+
}
|
|
23975
|
+
for (const definition of goals) {
|
|
23976
|
+
writeDefinition(staging, "goal", definition);
|
|
23977
|
+
versions[`goal:${definition.slug}`] = definition.version;
|
|
23978
|
+
}
|
|
23979
|
+
for (const definition of implementations) {
|
|
23980
|
+
writeDefinition(staging, "implementation", definition);
|
|
23981
|
+
versions[`implementation:${definition.slug}`] = definition.version;
|
|
23982
|
+
}
|
|
23983
|
+
for (const definition of assets) {
|
|
23984
|
+
writeDefinition(staging, "asset", definition);
|
|
23985
|
+
versions[`asset:${definition.slug}`] = definition.version;
|
|
23986
|
+
}
|
|
23987
|
+
const manifest = {
|
|
23988
|
+
schemaVersion: 1,
|
|
23989
|
+
tenantId: options.tenantId,
|
|
23990
|
+
hydratedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23991
|
+
versions: Object.fromEntries(Object.entries(versions).sort(([left], [right]) => left.localeCompare(right)))
|
|
23992
|
+
};
|
|
23993
|
+
fs16.writeFileSync(path17.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
23994
|
+
`, "utf8");
|
|
23995
|
+
fs16.rmSync(root, { recursive: true, force: true });
|
|
23996
|
+
fs16.renameSync(staging, root);
|
|
23997
|
+
return { root, tenantId: options.tenantId, versions: manifest.versions };
|
|
23998
|
+
} catch (error) {
|
|
23999
|
+
fs16.rmSync(staging, { recursive: true, force: true });
|
|
24000
|
+
throw error;
|
|
24001
|
+
}
|
|
24002
|
+
}
|
|
24003
|
+
async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env) {
|
|
24004
|
+
const tenantId2 = env.GITHUB_REPOSITORY?.trim();
|
|
24005
|
+
if (!hasStateBackendConfig(env)) {
|
|
24006
|
+
if (env.GITHUB_ACTIONS === "true") {
|
|
24007
|
+
throw new Error("GitHub Actions workflow identity is required for backend definitions");
|
|
24008
|
+
}
|
|
24009
|
+
return null;
|
|
24010
|
+
}
|
|
24011
|
+
if (!tenantId2) throw new Error("GITHUB_REPOSITORY is required for backend definitions");
|
|
24012
|
+
return hydrateDefinitions({
|
|
24013
|
+
cwd,
|
|
24014
|
+
tenantId: tenantId2,
|
|
24015
|
+
backend: createStateBackendFromEnv(env)
|
|
24016
|
+
});
|
|
24017
|
+
}
|
|
24018
|
+
|
|
23887
24019
|
// src/kody-cli.ts
|
|
23888
24020
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
23889
|
-
import * as
|
|
23890
|
-
import * as
|
|
24021
|
+
import * as fs49 from "fs";
|
|
24022
|
+
import * as path48 from "path";
|
|
23891
24023
|
|
|
23892
24024
|
// src/app-auth.ts
|
|
23893
24025
|
import { createSign } from "crypto";
|
|
@@ -24014,7 +24146,7 @@ init_config();
|
|
|
24014
24146
|
|
|
24015
24147
|
// src/dispatch.ts
|
|
24016
24148
|
init_config();
|
|
24017
|
-
import * as
|
|
24149
|
+
import * as fs17 from "fs";
|
|
24018
24150
|
|
|
24019
24151
|
// src/cron-match.ts
|
|
24020
24152
|
var FIELD_BOUNDS = [
|
|
@@ -24116,10 +24248,10 @@ function autoDispatch(opts) {
|
|
|
24116
24248
|
}
|
|
24117
24249
|
const eventName = process.env.GITHUB_EVENT_NAME;
|
|
24118
24250
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
24119
|
-
if (!eventName || !eventPath || !
|
|
24251
|
+
if (!eventName || !eventPath || !fs17.existsSync(eventPath)) return null;
|
|
24120
24252
|
let event = {};
|
|
24121
24253
|
try {
|
|
24122
|
-
event = JSON.parse(
|
|
24254
|
+
event = JSON.parse(fs17.readFileSync(eventPath, "utf-8"));
|
|
24123
24255
|
} catch {
|
|
24124
24256
|
return null;
|
|
24125
24257
|
}
|
|
@@ -24243,7 +24375,7 @@ function autoDispatchTyped(opts) {
|
|
|
24243
24375
|
if (legacy) return { kind: "route", ...legacy };
|
|
24244
24376
|
const eventName = process.env.GITHUB_EVENT_NAME;
|
|
24245
24377
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
24246
|
-
if (!eventName || !eventPath || !
|
|
24378
|
+
if (!eventName || !eventPath || !fs17.existsSync(eventPath)) {
|
|
24247
24379
|
return { kind: "silent", reason: "no GHA event context" };
|
|
24248
24380
|
}
|
|
24249
24381
|
if (eventName !== "issue_comment") {
|
|
@@ -24251,7 +24383,7 @@ function autoDispatchTyped(opts) {
|
|
|
24251
24383
|
}
|
|
24252
24384
|
let event = {};
|
|
24253
24385
|
try {
|
|
24254
|
-
event = JSON.parse(
|
|
24386
|
+
event = JSON.parse(fs17.readFileSync(eventPath, "utf-8"));
|
|
24255
24387
|
} catch {
|
|
24256
24388
|
return { kind: "silent", reason: "GHA event payload unreadable" };
|
|
24257
24389
|
}
|
|
@@ -24305,7 +24437,7 @@ function dispatchScheduledWatches(opts) {
|
|
|
24305
24437
|
for (const exe of listRuntimeProfilesForCwd(opts?.cwd ?? process.cwd())) {
|
|
24306
24438
|
let raw;
|
|
24307
24439
|
try {
|
|
24308
|
-
raw =
|
|
24440
|
+
raw = fs17.readFileSync(exe.profilePath, "utf-8");
|
|
24309
24441
|
} catch {
|
|
24310
24442
|
continue;
|
|
24311
24443
|
}
|
|
@@ -24700,9 +24832,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
24700
24832
|
return void 0;
|
|
24701
24833
|
}
|
|
24702
24834
|
function detectPackageManager2(cwd) {
|
|
24703
|
-
if (
|
|
24704
|
-
if (
|
|
24705
|
-
if (
|
|
24835
|
+
if (fs49.existsSync(path48.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
24836
|
+
if (fs49.existsSync(path48.join(cwd, "yarn.lock"))) return "yarn";
|
|
24837
|
+
if (fs49.existsSync(path48.join(cwd, "bun.lockb"))) return "bun";
|
|
24706
24838
|
return "npm";
|
|
24707
24839
|
}
|
|
24708
24840
|
function shouldChainScheduledWatch(match) {
|
|
@@ -24795,8 +24927,8 @@ function postFailureTail(issueNumber, cwd, reason) {
|
|
|
24795
24927
|
const logPath = lastRunLogPath(cwd);
|
|
24796
24928
|
let tail = "";
|
|
24797
24929
|
try {
|
|
24798
|
-
if (
|
|
24799
|
-
const content =
|
|
24930
|
+
if (fs49.existsSync(logPath)) {
|
|
24931
|
+
const content = fs49.readFileSync(logPath, "utf-8");
|
|
24800
24932
|
tail = content.slice(-3e3);
|
|
24801
24933
|
}
|
|
24802
24934
|
} catch {
|
|
@@ -24825,7 +24957,7 @@ async function runCi(argv) {
|
|
|
24825
24957
|
return 0;
|
|
24826
24958
|
}
|
|
24827
24959
|
const args = parseCiArgs(argv);
|
|
24828
|
-
const cwd = args.cwd ?
|
|
24960
|
+
const cwd = args.cwd ? path48.resolve(args.cwd) : process.cwd();
|
|
24829
24961
|
try {
|
|
24830
24962
|
const n = unpackAllSecrets();
|
|
24831
24963
|
if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
|
|
@@ -24884,9 +25016,9 @@ async function runCi(argv) {
|
|
|
24884
25016
|
forceRunCliArgs = { goal: envForceMessage };
|
|
24885
25017
|
}
|
|
24886
25018
|
}
|
|
24887
|
-
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath &&
|
|
25019
|
+
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath && fs49.existsSync(dispatchEventPath)) {
|
|
24888
25020
|
try {
|
|
24889
|
-
const evt = JSON.parse(
|
|
25021
|
+
const evt = JSON.parse(fs49.readFileSync(dispatchEventPath, "utf-8"));
|
|
24890
25022
|
const inputs = objectValue2(evt.inputs);
|
|
24891
25023
|
const issueInput = parseInt(String(inputs?.issue_number ?? ""), 10);
|
|
24892
25024
|
const sessionInput = String(inputs?.sessionId ?? "");
|
|
@@ -25293,8 +25425,8 @@ init_repoWorkspace();
|
|
|
25293
25425
|
|
|
25294
25426
|
// src/scripts/brainTurnLog.ts
|
|
25295
25427
|
init_runtimePaths();
|
|
25296
|
-
import * as
|
|
25297
|
-
import * as
|
|
25428
|
+
import * as fs50 from "fs";
|
|
25429
|
+
import * as path49 from "path";
|
|
25298
25430
|
import posixPath4 from "path/posix";
|
|
25299
25431
|
var live = /* @__PURE__ */ new Map();
|
|
25300
25432
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -25302,8 +25434,8 @@ function brainEventsFilePath(dir, chatId) {
|
|
|
25302
25434
|
}
|
|
25303
25435
|
function lastPersistedSeq(dir, chatId) {
|
|
25304
25436
|
const p = brainEventsFilePath(dir, chatId);
|
|
25305
|
-
if (!
|
|
25306
|
-
const lines =
|
|
25437
|
+
if (!fs50.existsSync(p)) return 0;
|
|
25438
|
+
const lines = fs50.readFileSync(p, "utf-8").split("\n").filter(Boolean);
|
|
25307
25439
|
if (lines.length === 0) return 0;
|
|
25308
25440
|
try {
|
|
25309
25441
|
return JSON.parse(lines[lines.length - 1]).seq || 0;
|
|
@@ -25313,9 +25445,9 @@ function lastPersistedSeq(dir, chatId) {
|
|
|
25313
25445
|
}
|
|
25314
25446
|
function readSince(dir, chatId, since) {
|
|
25315
25447
|
const p = brainEventsFilePath(dir, chatId);
|
|
25316
|
-
if (!
|
|
25448
|
+
if (!fs50.existsSync(p)) return [];
|
|
25317
25449
|
const out = [];
|
|
25318
|
-
for (const line of
|
|
25450
|
+
for (const line of fs50.readFileSync(p, "utf-8").split("\n")) {
|
|
25319
25451
|
if (!line) continue;
|
|
25320
25452
|
try {
|
|
25321
25453
|
const rec = JSON.parse(line);
|
|
@@ -25341,12 +25473,12 @@ function beginTurn(dir, chatId) {
|
|
|
25341
25473
|
};
|
|
25342
25474
|
live.set(chatId, state);
|
|
25343
25475
|
const p = brainEventsFilePath(dir, chatId);
|
|
25344
|
-
|
|
25476
|
+
fs50.mkdirSync(path49.dirname(p), { recursive: true });
|
|
25345
25477
|
return (event) => {
|
|
25346
25478
|
state.seq += 1;
|
|
25347
25479
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
25348
25480
|
try {
|
|
25349
|
-
|
|
25481
|
+
fs50.appendFileSync(p, `${JSON.stringify(rec)}
|
|
25350
25482
|
`);
|
|
25351
25483
|
} catch (err) {
|
|
25352
25484
|
process.stderr.write(
|
|
@@ -25385,7 +25517,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
|
|
|
25385
25517
|
event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
|
|
25386
25518
|
};
|
|
25387
25519
|
try {
|
|
25388
|
-
|
|
25520
|
+
fs50.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
|
|
25389
25521
|
`);
|
|
25390
25522
|
} catch {
|
|
25391
25523
|
}
|
|
@@ -25590,6 +25722,25 @@ var BrokerSink = class {
|
|
|
25590
25722
|
function hasStateBackendConfig2(env = process.env) {
|
|
25591
25723
|
return Boolean(env.CONVEX_URL?.trim() && env.KODY_SERVICE_KEY?.trim());
|
|
25592
25724
|
}
|
|
25725
|
+
var definitionHydrations = /* @__PURE__ */ new Map();
|
|
25726
|
+
async function hydrateBrainDefinitions(options) {
|
|
25727
|
+
const env = options.env ?? process.env;
|
|
25728
|
+
if (!options.repo || !hasStateBackendConfig2(env)) return;
|
|
25729
|
+
const key = `${options.cwd}\0${options.repo}`;
|
|
25730
|
+
const running = definitionHydrations.get(key);
|
|
25731
|
+
if (running) return running;
|
|
25732
|
+
const hydration = hydrateDefinitions({
|
|
25733
|
+
cwd: options.cwd,
|
|
25734
|
+
tenantId: options.repo,
|
|
25735
|
+
backend: options.backend ?? createStateBackendFromEnv(env)
|
|
25736
|
+
}).then(() => void 0).finally(() => {
|
|
25737
|
+
if (definitionHydrations.get(key) === hydration) {
|
|
25738
|
+
definitionHydrations.delete(key);
|
|
25739
|
+
}
|
|
25740
|
+
});
|
|
25741
|
+
definitionHydrations.set(key, hydration);
|
|
25742
|
+
return hydration;
|
|
25743
|
+
}
|
|
25593
25744
|
var chatQueues = /* @__PURE__ */ new Map();
|
|
25594
25745
|
function enqueue(chatId, fn) {
|
|
25595
25746
|
const prev = chatQueues.get(chatId) ?? Promise.resolve();
|
|
@@ -25689,6 +25840,17 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
25689
25840
|
res.end();
|
|
25690
25841
|
return;
|
|
25691
25842
|
}
|
|
25843
|
+
try {
|
|
25844
|
+
await hydrateBrainDefinitions({ cwd: agentCwd, repo });
|
|
25845
|
+
} catch (err) {
|
|
25846
|
+
emitSse(res, {
|
|
25847
|
+
type: "error",
|
|
25848
|
+
chatId,
|
|
25849
|
+
error: `Definition hydration failed: ${err instanceof Error ? err.message : String(err)}`
|
|
25850
|
+
});
|
|
25851
|
+
res.end();
|
|
25852
|
+
return;
|
|
25853
|
+
}
|
|
25692
25854
|
const stateToken = repoToken || envGithubToken();
|
|
25693
25855
|
const sessionFile = sessionFilePath(agentCwd, chatId);
|
|
25694
25856
|
const sessionStore = opts.createStore({
|
|
@@ -25748,7 +25910,7 @@ function buildServer(opts) {
|
|
|
25748
25910
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
25749
25911
|
const createStore = opts.createStore ?? createSessionStore;
|
|
25750
25912
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
25751
|
-
const reposRoot = opts.reposRoot ??
|
|
25913
|
+
const reposRoot = opts.reposRoot ?? path50.join(path50.dirname(path50.resolve(opts.cwd)), "repos");
|
|
25752
25914
|
return createServer2(async (req, res) => {
|
|
25753
25915
|
if (!req.method || !req.url) {
|
|
25754
25916
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -26352,7 +26514,7 @@ async function loadConfigSafe() {
|
|
|
26352
26514
|
}
|
|
26353
26515
|
|
|
26354
26516
|
// src/chat-cli.ts
|
|
26355
|
-
import * as
|
|
26517
|
+
import * as path51 from "path";
|
|
26356
26518
|
|
|
26357
26519
|
// src/chat/inbox.ts
|
|
26358
26520
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
@@ -26633,7 +26795,7 @@ async function runChat(argv) {
|
|
|
26633
26795
|
${CHAT_HELP}`);
|
|
26634
26796
|
return 64;
|
|
26635
26797
|
}
|
|
26636
|
-
const cwd = args.cwd ?
|
|
26798
|
+
const cwd = args.cwd ? path51.resolve(args.cwd) : process.cwd();
|
|
26637
26799
|
const sessionId = args.sessionId;
|
|
26638
26800
|
const runRequest = readRunRequestFromEnv();
|
|
26639
26801
|
if (runRequest && "request" in runRequest) {
|
|
@@ -26751,140 +26913,6 @@ ${CHAT_HELP}`);
|
|
|
26751
26913
|
// src/entry.ts
|
|
26752
26914
|
init_config();
|
|
26753
26915
|
init_definition_paths();
|
|
26754
|
-
|
|
26755
|
-
// src/definition-hydration.ts
|
|
26756
|
-
init_state_backend();
|
|
26757
|
-
import { createHash as createHash8 } from "crypto";
|
|
26758
|
-
import * as fs50 from "fs";
|
|
26759
|
-
import * as path51 from "path";
|
|
26760
|
-
var SLUG_RE2 = /^[a-z0-9][a-z0-9_-]{0,127}$/;
|
|
26761
|
-
function assertSafeDefinitionPath(filePath) {
|
|
26762
|
-
const segments = filePath.split("/");
|
|
26763
|
-
if (!filePath || filePath.startsWith("/") || filePath.includes("\\") || filePath.includes("\0") || segments.some((segment) => !segment || segment === "." || segment === "..")) {
|
|
26764
|
-
throw new Error(`unsafe definition path: ${filePath}`);
|
|
26765
|
-
}
|
|
26766
|
-
}
|
|
26767
|
-
function normalizeDefinitionBundle(bundle) {
|
|
26768
|
-
if (bundle.schemaVersion !== 1) throw new Error("unsupported definition bundle schema");
|
|
26769
|
-
const files = Object.fromEntries(
|
|
26770
|
-
Object.entries(bundle.files).sort(([left], [right]) => left.localeCompare(right)).map(([filePath, content]) => {
|
|
26771
|
-
assertSafeDefinitionPath(filePath);
|
|
26772
|
-
return [filePath, content.replace(/\r\n?/g, "\n")];
|
|
26773
|
-
})
|
|
26774
|
-
);
|
|
26775
|
-
return { schemaVersion: 1, files };
|
|
26776
|
-
}
|
|
26777
|
-
function definitionVersion(bundle) {
|
|
26778
|
-
return `sha256:${createHash8("sha256").update(JSON.stringify(normalizeDefinitionBundle(bundle))).digest("hex")}`;
|
|
26779
|
-
}
|
|
26780
|
-
function verifyDefinition(definition) {
|
|
26781
|
-
if (!SLUG_RE2.test(definition.slug)) throw new Error(`invalid definition slug: ${definition.slug}`);
|
|
26782
|
-
const bundle = normalizeDefinitionBundle(definition.bundle);
|
|
26783
|
-
if (definitionVersion(bundle) !== definition.version) {
|
|
26784
|
-
throw new Error(`definition version mismatch for ${definition.slug}: ${definition.version}`);
|
|
26785
|
-
}
|
|
26786
|
-
return bundle;
|
|
26787
|
-
}
|
|
26788
|
-
function writeBundle(root, bundle) {
|
|
26789
|
-
for (const [filePath, contents] of Object.entries(bundle.files)) {
|
|
26790
|
-
const target = path51.join(root, filePath);
|
|
26791
|
-
fs50.mkdirSync(path51.dirname(target), { recursive: true });
|
|
26792
|
-
fs50.writeFileSync(target, contents, "utf8");
|
|
26793
|
-
}
|
|
26794
|
-
}
|
|
26795
|
-
function writeDefinition(root, kind, definition) {
|
|
26796
|
-
const bundle = verifyDefinition(definition);
|
|
26797
|
-
if (kind === "agent") {
|
|
26798
|
-
const raw = bundle.files["agent.md"];
|
|
26799
|
-
if (typeof raw !== "string") throw new Error(`agent definition ${definition.slug} is missing agent.md`);
|
|
26800
|
-
fs50.writeFileSync(path51.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
|
|
26801
|
-
return;
|
|
26802
|
-
}
|
|
26803
|
-
if (kind === "goal") {
|
|
26804
|
-
writeBundle(path51.join(root, "goals", definition.slug), bundle);
|
|
26805
|
-
return;
|
|
26806
|
-
}
|
|
26807
|
-
if (kind === "implementation") {
|
|
26808
|
-
writeBundle(path51.join(root, "implementations", definition.slug), bundle);
|
|
26809
|
-
return;
|
|
26810
|
-
}
|
|
26811
|
-
if (kind === "asset") {
|
|
26812
|
-
writeBundle(path51.join(root, "shared"), bundle);
|
|
26813
|
-
return;
|
|
26814
|
-
}
|
|
26815
|
-
writeBundle(path51.join(root, "capabilities", definition.slug), bundle);
|
|
26816
|
-
}
|
|
26817
|
-
async function hydrateDefinitions(options) {
|
|
26818
|
-
const root = path51.join(options.cwd, ".kody-engine", "definitions");
|
|
26819
|
-
const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
|
|
26820
|
-
fs50.rmSync(staging, { recursive: true, force: true });
|
|
26821
|
-
fs50.mkdirSync(path51.join(staging, "agents"), { recursive: true });
|
|
26822
|
-
fs50.mkdirSync(path51.join(staging, "capabilities"), { recursive: true });
|
|
26823
|
-
fs50.mkdirSync(path51.join(staging, "goals"), { recursive: true });
|
|
26824
|
-
fs50.mkdirSync(path51.join(staging, "implementations"), { recursive: true });
|
|
26825
|
-
fs50.mkdirSync(path51.join(staging, "shared"), { recursive: true });
|
|
26826
|
-
try {
|
|
26827
|
-
const [capabilities, agents, goals, implementations, assets] = await Promise.all([
|
|
26828
|
-
options.backend.listDefinitions(options.tenantId, "capability"),
|
|
26829
|
-
options.backend.listDefinitions(options.tenantId, "agent"),
|
|
26830
|
-
options.backend.listDefinitions(options.tenantId, "goal"),
|
|
26831
|
-
options.backend.listDefinitions(options.tenantId, "implementation"),
|
|
26832
|
-
options.backend.listDefinitions(options.tenantId, "asset")
|
|
26833
|
-
]);
|
|
26834
|
-
const versions = {};
|
|
26835
|
-
for (const definition of capabilities) {
|
|
26836
|
-
writeDefinition(staging, "capability", definition);
|
|
26837
|
-
versions[`capability:${definition.slug}`] = definition.version;
|
|
26838
|
-
}
|
|
26839
|
-
for (const definition of agents) {
|
|
26840
|
-
writeDefinition(staging, "agent", definition);
|
|
26841
|
-
versions[`agent:${definition.slug}`] = definition.version;
|
|
26842
|
-
}
|
|
26843
|
-
for (const definition of goals) {
|
|
26844
|
-
writeDefinition(staging, "goal", definition);
|
|
26845
|
-
versions[`goal:${definition.slug}`] = definition.version;
|
|
26846
|
-
}
|
|
26847
|
-
for (const definition of implementations) {
|
|
26848
|
-
writeDefinition(staging, "implementation", definition);
|
|
26849
|
-
versions[`implementation:${definition.slug}`] = definition.version;
|
|
26850
|
-
}
|
|
26851
|
-
for (const definition of assets) {
|
|
26852
|
-
writeDefinition(staging, "asset", definition);
|
|
26853
|
-
versions[`asset:${definition.slug}`] = definition.version;
|
|
26854
|
-
}
|
|
26855
|
-
const manifest = {
|
|
26856
|
-
schemaVersion: 1,
|
|
26857
|
-
tenantId: options.tenantId,
|
|
26858
|
-
hydratedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26859
|
-
versions: Object.fromEntries(Object.entries(versions).sort(([left], [right]) => left.localeCompare(right)))
|
|
26860
|
-
};
|
|
26861
|
-
fs50.writeFileSync(path51.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
26862
|
-
`, "utf8");
|
|
26863
|
-
fs50.rmSync(root, { recursive: true, force: true });
|
|
26864
|
-
fs50.renameSync(staging, root);
|
|
26865
|
-
return { root, tenantId: options.tenantId, versions: manifest.versions };
|
|
26866
|
-
} catch (error) {
|
|
26867
|
-
fs50.rmSync(staging, { recursive: true, force: true });
|
|
26868
|
-
throw error;
|
|
26869
|
-
}
|
|
26870
|
-
}
|
|
26871
|
-
async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env) {
|
|
26872
|
-
const tenantId2 = env.GITHUB_REPOSITORY?.trim();
|
|
26873
|
-
if (!hasStateBackendConfig(env)) {
|
|
26874
|
-
if (env.GITHUB_ACTIONS === "true") {
|
|
26875
|
-
throw new Error("GitHub Actions workflow identity is required for backend definitions");
|
|
26876
|
-
}
|
|
26877
|
-
return null;
|
|
26878
|
-
}
|
|
26879
|
-
if (!tenantId2) throw new Error("GITHUB_REPOSITORY is required for backend definitions");
|
|
26880
|
-
return hydrateDefinitions({
|
|
26881
|
-
cwd,
|
|
26882
|
-
tenantId: tenantId2,
|
|
26883
|
-
backend: createStateBackendFromEnv(env)
|
|
26884
|
-
});
|
|
26885
|
-
}
|
|
26886
|
-
|
|
26887
|
-
// src/entry.ts
|
|
26888
26916
|
init_job();
|
|
26889
26917
|
init_registry();
|
|
26890
26918
|
|
|
@@ -28433,9 +28461,10 @@ function parseArgs(argv) {
|
|
|
28433
28461
|
}
|
|
28434
28462
|
async function main(argv = process.argv.slice(2)) {
|
|
28435
28463
|
unpackAllSecrets();
|
|
28464
|
+
const args = parseArgs(argv);
|
|
28436
28465
|
const cwdFlag = argv.indexOf("--cwd");
|
|
28437
28466
|
const definitionCwd = cwdFlag >= 0 && argv[cwdFlag + 1] ? argv[cwdFlag + 1] : process.cwd();
|
|
28438
|
-
const shouldHydrate = !hasExplicitDefinitionsRoot(definitionCwd) && (Boolean(process.env.CONVEX_URL?.trim()) || process.env.GITHUB_ACTIONS === "true" && Boolean(process.env.GITHUB_EVENT_NAME));
|
|
28467
|
+
const shouldHydrate = !(args.command === "server" && args.serverName === "brain-serve") && !hasExplicitDefinitionsRoot(definitionCwd) && (Boolean(process.env.CONVEX_URL?.trim()) || process.env.GITHUB_ACTIONS === "true" && Boolean(process.env.GITHUB_EVENT_NAME));
|
|
28439
28468
|
if (shouldHydrate) {
|
|
28440
28469
|
try {
|
|
28441
28470
|
await hydrateDefinitionsFromEnv(definitionCwd);
|
|
@@ -28446,7 +28475,6 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
28446
28475
|
return 99;
|
|
28447
28476
|
}
|
|
28448
28477
|
}
|
|
28449
|
-
const args = parseArgs(argv);
|
|
28450
28478
|
if (args.errors.length > 0) {
|
|
28451
28479
|
for (const e of args.errors) process.stderr.write(`error: ${e}
|
|
28452
28480
|
`);
|