@kody-ade/kody-engine 0.4.435 → 0.4.436
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/kody.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "@kody-ade/kody-engine",
|
|
18
|
-
version: "0.4.
|
|
18
|
+
version: "0.4.436",
|
|
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",
|
|
@@ -1104,7 +1104,7 @@ function cmsHeaders(opts) {
|
|
|
1104
1104
|
}
|
|
1105
1105
|
};
|
|
1106
1106
|
}
|
|
1107
|
-
async function callDashboardCms(opts,
|
|
1107
|
+
async function callDashboardCms(opts, path54, init = {}) {
|
|
1108
1108
|
const baseUrl = dashboardBaseUrl(opts);
|
|
1109
1109
|
if (!baseUrl) {
|
|
1110
1110
|
return {
|
|
@@ -1116,7 +1116,7 @@ async function callDashboardCms(opts, path52, init = {}) {
|
|
|
1116
1116
|
const headerResult = cmsHeaders(opts);
|
|
1117
1117
|
if (!headerResult.ok) return headerResult;
|
|
1118
1118
|
try {
|
|
1119
|
-
const res = await fetch(`${baseUrl}${
|
|
1119
|
+
const res = await fetch(`${baseUrl}${path54}`, {
|
|
1120
1120
|
...init,
|
|
1121
1121
|
headers: {
|
|
1122
1122
|
...headerResult.headers,
|
|
@@ -1188,8 +1188,8 @@ function documentArg(value) {
|
|
|
1188
1188
|
function normalizeCmsDocumentIdInput(input) {
|
|
1189
1189
|
const trimmed = stripWrappingQuotes(input.trim());
|
|
1190
1190
|
const withoutQuery = trimmed.split(/[?#]/, 1)[0] ?? trimmed;
|
|
1191
|
-
const
|
|
1192
|
-
return
|
|
1191
|
+
const path54 = parseDocumentPath(withoutQuery);
|
|
1192
|
+
return path54 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
|
|
1193
1193
|
}
|
|
1194
1194
|
function stripWrappingQuotes(value) {
|
|
1195
1195
|
let current = value;
|
|
@@ -1200,9 +1200,9 @@ function stripWrappingQuotes(value) {
|
|
|
1200
1200
|
}
|
|
1201
1201
|
}
|
|
1202
1202
|
function parseDocumentPath(value) {
|
|
1203
|
-
const
|
|
1204
|
-
if (!
|
|
1205
|
-
const parts =
|
|
1203
|
+
const path54 = value.startsWith("http://") || value.startsWith("https://") ? urlPathname(value) : value;
|
|
1204
|
+
if (!path54?.includes("/content/entries/")) return null;
|
|
1205
|
+
const parts = path54.split("/").filter(Boolean).map(decodePathPart);
|
|
1206
1206
|
const entriesIndex = parts.findIndex((part, index) => part === "content" && parts[index + 1] === "entries");
|
|
1207
1207
|
const idPart = parts[entriesIndex + 3];
|
|
1208
1208
|
if (!idPart || idPart === "new") return null;
|
|
@@ -1646,56 +1646,6 @@ var init_issue = __esm({
|
|
|
1646
1646
|
}
|
|
1647
1647
|
});
|
|
1648
1648
|
|
|
1649
|
-
// src/agency/implementation-resolution.ts
|
|
1650
|
-
function resolveCapabilityImplementation(input) {
|
|
1651
|
-
const compatible = input.implementations.filter(
|
|
1652
|
-
(implementation) => implementation.capabilityRef.id === input.capabilityId && implementation.compatibleCapabilityRevision === input.capabilityRevision
|
|
1653
|
-
);
|
|
1654
|
-
if (input.explicitOverride) {
|
|
1655
|
-
if (!input.authorizeOverride?.(input.explicitOverride)) {
|
|
1656
|
-
throw new ImplementationResolutionError(`Implementation override "${input.explicitOverride}" is not authorized`);
|
|
1657
|
-
}
|
|
1658
|
-
return selectNamed(input.explicitOverride, input, compatible, "override");
|
|
1659
|
-
}
|
|
1660
|
-
if (input.repositoryBinding) {
|
|
1661
|
-
return selectNamed(input.repositoryBinding, input, compatible, "repository binding");
|
|
1662
|
-
}
|
|
1663
|
-
if (compatible.length === 1) return compatible[0];
|
|
1664
|
-
if (compatible.length === 0) {
|
|
1665
|
-
throw new ImplementationResolutionError(
|
|
1666
|
-
`No compatible Implementation is available for Capability "${input.capabilityId}" at revision "${input.capabilityRevision}"`
|
|
1667
|
-
);
|
|
1668
|
-
}
|
|
1669
|
-
throw new ImplementationResolutionError(
|
|
1670
|
-
`Capability "${input.capabilityId}" has ${compatible.length} compatible Implementations; configure a repository binding`
|
|
1671
|
-
);
|
|
1672
|
-
}
|
|
1673
|
-
function selectNamed(id, input, compatible, source) {
|
|
1674
|
-
const known = input.implementations.find((implementation) => implementation.id === id);
|
|
1675
|
-
if (!known) {
|
|
1676
|
-
throw new ImplementationResolutionError(`Implementation ${source} "${id}" is not available`);
|
|
1677
|
-
}
|
|
1678
|
-
const selected = compatible.find((implementation) => implementation.id === id);
|
|
1679
|
-
if (!selected) {
|
|
1680
|
-
throw new ImplementationResolutionError(
|
|
1681
|
-
`Implementation ${source} "${id}" is not compatible with Capability "${input.capabilityId}" at revision "${input.capabilityRevision}"`
|
|
1682
|
-
);
|
|
1683
|
-
}
|
|
1684
|
-
return selected;
|
|
1685
|
-
}
|
|
1686
|
-
var ImplementationResolutionError;
|
|
1687
|
-
var init_implementation_resolution = __esm({
|
|
1688
|
-
"src/agency/implementation-resolution.ts"() {
|
|
1689
|
-
"use strict";
|
|
1690
|
-
ImplementationResolutionError = class extends Error {
|
|
1691
|
-
constructor(message) {
|
|
1692
|
-
super(message);
|
|
1693
|
-
this.name = "ImplementationResolutionError";
|
|
1694
|
-
}
|
|
1695
|
-
};
|
|
1696
|
-
}
|
|
1697
|
-
});
|
|
1698
|
-
|
|
1699
1649
|
// src/capabilityFolders.ts
|
|
1700
1650
|
import * as fs4 from "fs";
|
|
1701
1651
|
import * as path5 from "path";
|
|
@@ -1731,19 +1681,29 @@ function listCapabilityFolderSlugs(absDir) {
|
|
|
1731
1681
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(path5.join(absDir, e.name))).map((e) => e.name).sort();
|
|
1732
1682
|
}
|
|
1733
1683
|
function isCapabilityFolder(dir) {
|
|
1734
|
-
|
|
1684
|
+
if (!fs4.existsSync(path5.join(dir, CAPABILITY_DEFINITION_FILE))) return false;
|
|
1685
|
+
if (!fs4.existsSync(path5.join(dir, CAPABILITY_BODY_FILE))) return false;
|
|
1686
|
+
const entries = fs4.readdirSync(dir, { withFileTypes: true });
|
|
1687
|
+
return entries.every(
|
|
1688
|
+
(entry) => entry.name === CAPABILITY_DEFINITION_FILE || entry.name === CAPABILITY_BODY_FILE || entry.isDirectory() && (entry.name === "skills" || entry.name === "tools")
|
|
1689
|
+
);
|
|
1735
1690
|
}
|
|
1736
1691
|
function readCapabilityFolder(root, slug) {
|
|
1737
1692
|
const dir = path5.join(root, slug);
|
|
1738
1693
|
const definitionPath = path5.join(dir, CAPABILITY_DEFINITION_FILE);
|
|
1739
|
-
const
|
|
1740
|
-
const profilePath = fs4.existsSync(definitionPath) ? definitionPath : legacyProfilePath;
|
|
1694
|
+
const profilePath = definitionPath;
|
|
1741
1695
|
const bodyPath = path5.join(dir, CAPABILITY_BODY_FILE);
|
|
1742
1696
|
if (!fs4.existsSync(profilePath) || !fs4.statSync(profilePath).isFile()) return null;
|
|
1743
1697
|
if (!fs4.existsSync(bodyPath) || !fs4.statSync(bodyPath).isFile()) return null;
|
|
1744
1698
|
try {
|
|
1745
1699
|
const rawDefinition = JSON.parse(fs4.readFileSync(profilePath, "utf-8"));
|
|
1746
|
-
const
|
|
1700
|
+
const contract = parseCapabilityContract(rawDefinition);
|
|
1701
|
+
if (!contract) return null;
|
|
1702
|
+
const rawProfile = {
|
|
1703
|
+
inputSchema: contract.input.schema,
|
|
1704
|
+
outputSchema: contract.output.schema,
|
|
1705
|
+
contract
|
|
1706
|
+
};
|
|
1747
1707
|
const rawBody = fs4.readFileSync(bodyPath, "utf-8");
|
|
1748
1708
|
const { title, body } = parseCapabilityBody(rawBody, slug);
|
|
1749
1709
|
return {
|
|
@@ -1754,54 +1714,28 @@ function readCapabilityFolder(root, slug) {
|
|
|
1754
1714
|
title,
|
|
1755
1715
|
body,
|
|
1756
1716
|
rawBody,
|
|
1757
|
-
config:
|
|
1717
|
+
config: {
|
|
1718
|
+
action: slug,
|
|
1719
|
+
describe: title,
|
|
1720
|
+
outputSchema: contract.output.schema
|
|
1721
|
+
},
|
|
1758
1722
|
rawProfile
|
|
1759
1723
|
};
|
|
1760
1724
|
} catch {
|
|
1761
1725
|
return null;
|
|
1762
1726
|
}
|
|
1763
1727
|
}
|
|
1764
|
-
function
|
|
1765
|
-
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
capabilityKind: parseCapabilityKind(raw.capabilityKind),
|
|
1772
|
-
disabled: typeof raw.disabled === "boolean" ? raw.disabled : void 0,
|
|
1773
|
-
internal: typeof raw.internal === "boolean" ? raw.internal : void 0,
|
|
1774
|
-
public: typeof raw.public === "boolean" ? raw.public : void 0,
|
|
1775
|
-
agent: stringField(raw.agent),
|
|
1776
|
-
mentions: stringList(raw.mentions).map((m) => m.replace(/^@/, "")),
|
|
1777
|
-
tools,
|
|
1778
|
-
capabilityTools: tools,
|
|
1779
|
-
capabilityToolMode: parseCapabilityToolMode(raw.capabilityToolMode),
|
|
1780
|
-
implementations,
|
|
1781
|
-
role: stringField(raw.role),
|
|
1782
|
-
describe: stringField(raw.describe) ?? stringField(raw.purpose),
|
|
1783
|
-
stage: stringField(raw.stage),
|
|
1784
|
-
readsFrom: stringList(raw.readsFrom ?? raw.reads_from),
|
|
1785
|
-
writesTo: stringList(raw.writesTo ?? raw.writes_to),
|
|
1786
|
-
output: parseCapabilityOutput(raw.output),
|
|
1787
|
-
outputSchema: isPlainObject(raw.outputSchema) ? raw.outputSchema : void 0,
|
|
1788
|
-
workflow: parseCapabilityWorkflow(raw.workflow)
|
|
1728
|
+
function parseCapabilityContract(raw) {
|
|
1729
|
+
if (Object.keys(raw).length !== 2 || !isPlainObject(raw.input) || !isPlainObject(raw.output)) return null;
|
|
1730
|
+
const parseValue = (value) => {
|
|
1731
|
+
if (Object.keys(value).some((key) => key !== "name" && key !== "schema") || typeof value.name !== "string" || !/^[a-z][a-z0-9-]*$/.test(value.name) || !isPlainObject(value.schema)) {
|
|
1732
|
+
return null;
|
|
1733
|
+
}
|
|
1734
|
+
return { name: value.name, schema: value.schema };
|
|
1789
1735
|
};
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
const result = raw.result;
|
|
1794
|
-
if (!result || typeof result !== "object" || Array.isArray(result)) return void 0;
|
|
1795
|
-
const facts = stringList(result.facts);
|
|
1796
|
-
return { result: { facts } };
|
|
1797
|
-
}
|
|
1798
|
-
function parseCapabilityKind(raw) {
|
|
1799
|
-
return raw === "observe" || raw === "act" || raw === "verify" ? raw : void 0;
|
|
1800
|
-
}
|
|
1801
|
-
function parseCapabilityToolMode(raw) {
|
|
1802
|
-
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
1803
|
-
if (raw === "lock" || raw === "append") return raw;
|
|
1804
|
-
return void 0;
|
|
1736
|
+
const input = parseValue(raw.input);
|
|
1737
|
+
const output = parseValue(raw.output);
|
|
1738
|
+
return input && output ? { input, output } : null;
|
|
1805
1739
|
}
|
|
1806
1740
|
function parseCapabilityBody(raw, slug) {
|
|
1807
1741
|
const trimmed = raw.trim();
|
|
@@ -1859,7 +1793,6 @@ function parseWorkflowStep(value) {
|
|
|
1859
1793
|
const id = stringField(raw.id);
|
|
1860
1794
|
const action = stringField(raw.action);
|
|
1861
1795
|
const evidence = stringField(raw.evidence);
|
|
1862
|
-
const agent = stringField(raw.agent);
|
|
1863
1796
|
const reason = stringField(raw.reason);
|
|
1864
1797
|
const target = stringField(raw.target);
|
|
1865
1798
|
const targetFact = stringField(raw.targetFact ?? raw.target_fact);
|
|
@@ -1875,7 +1808,6 @@ function parseWorkflowStep(value) {
|
|
|
1875
1808
|
...evidence ? { evidence } : {},
|
|
1876
1809
|
...target === "issue" || target === "pr" ? { target } : {},
|
|
1877
1810
|
...targetFact ? { targetFact } : {},
|
|
1878
|
-
...agent && isSafeSlug(agent) ? { agent } : {},
|
|
1879
1811
|
...reason ? { reason } : {},
|
|
1880
1812
|
...cliArgs && typeof cliArgs === "object" && !Array.isArray(cliArgs) ? { cliArgs } : {},
|
|
1881
1813
|
...inputs ? { inputs } : {},
|
|
@@ -1957,9 +1889,9 @@ var CAPABILITY_PROFILE_FILE, CAPABILITY_DEFINITION_FILE, CAPABILITY_BODY_FILE;
|
|
|
1957
1889
|
var init_capabilityFolders = __esm({
|
|
1958
1890
|
"src/capabilityFolders.ts"() {
|
|
1959
1891
|
"use strict";
|
|
1960
|
-
CAPABILITY_PROFILE_FILE = "
|
|
1961
|
-
CAPABILITY_DEFINITION_FILE = "
|
|
1962
|
-
CAPABILITY_BODY_FILE = "
|
|
1892
|
+
CAPABILITY_PROFILE_FILE = "contract.json";
|
|
1893
|
+
CAPABILITY_DEFINITION_FILE = "contract.json";
|
|
1894
|
+
CAPABILITY_BODY_FILE = "instructions.md";
|
|
1963
1895
|
}
|
|
1964
1896
|
});
|
|
1965
1897
|
|
|
@@ -1997,7 +1929,6 @@ var init_definition_paths = __esm({
|
|
|
1997
1929
|
});
|
|
1998
1930
|
|
|
1999
1931
|
// src/registry.ts
|
|
2000
|
-
import { createHash as createHash2 } from "crypto";
|
|
2001
1932
|
import * as fs6 from "fs";
|
|
2002
1933
|
import * as path7 from "path";
|
|
2003
1934
|
function getImplementationsRoot() {
|
|
@@ -2049,10 +1980,12 @@ function getImplementationRoots() {
|
|
|
2049
1980
|
return getImplementationRootsForCwd(process.cwd());
|
|
2050
1981
|
}
|
|
2051
1982
|
function getImplementationRootsForCwd(cwd) {
|
|
2052
|
-
|
|
1983
|
+
void cwd;
|
|
1984
|
+
return [getImplementationsRoot()];
|
|
2053
1985
|
}
|
|
2054
1986
|
function getRuntimeProfileRootsForCwd(cwd) {
|
|
2055
|
-
|
|
1987
|
+
const roots = [...getImplementationRootsForCwd(cwd), getRuntimeServicesRoot()];
|
|
1988
|
+
return process.env.NODE_ENV === "test" ? [implementationsRoot(cwd), ...roots] : roots;
|
|
2056
1989
|
}
|
|
2057
1990
|
function getCapabilityRoots(projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
|
|
2058
1991
|
return [projectCapabilitiesRoot, getBuiltinCapabilitiesRoot()];
|
|
@@ -2127,7 +2060,7 @@ function getCapabilityActionInputs(action, projectCapabilitiesRoot = getProjectC
|
|
|
2127
2060
|
const resolved = resolveCapabilityAction(action, projectCapabilitiesRoot);
|
|
2128
2061
|
if (!resolved) return null;
|
|
2129
2062
|
const capability = resolveCapabilityFolder(resolved.capability, projectCapabilitiesRoot);
|
|
2130
|
-
if (capability && path7.basename(capability.profilePath) === "
|
|
2063
|
+
if (capability && path7.basename(capability.profilePath) === "contract.json") {
|
|
2131
2064
|
const schema = capability.rawProfile.inputSchema;
|
|
2132
2065
|
if (!schema || typeof schema !== "object" || Array.isArray(schema)) return [];
|
|
2133
2066
|
const properties = schema.properties;
|
|
@@ -2151,17 +2084,8 @@ function getCapabilityActionInputs(action, projectCapabilitiesRoot = getProjectC
|
|
|
2151
2084
|
return getProfileInputs(resolved.implementation);
|
|
2152
2085
|
}
|
|
2153
2086
|
function resolveCapabilityExecution(capability, cwd = process.cwd()) {
|
|
2154
|
-
if (path7.basename(capability.profilePath) === "
|
|
2155
|
-
|
|
2156
|
-
const definition = JSON.parse(fs6.readFileSync(capability.profilePath, "utf-8"));
|
|
2157
|
-
const capabilityRevision = createHash2("sha256").update(canonical(definition)).digest("hex");
|
|
2158
|
-
const selected = resolveCapabilityImplementation({
|
|
2159
|
-
capabilityId: capability.slug,
|
|
2160
|
-
capabilityRevision,
|
|
2161
|
-
implementations,
|
|
2162
|
-
repositoryBinding: repositoryImplementationBinding(capability.slug, cwd)
|
|
2163
|
-
});
|
|
2164
|
-
return { implementation: selected.id, cliArgs: {} };
|
|
2087
|
+
if (path7.basename(capability.profilePath) === "contract.json") {
|
|
2088
|
+
return { implementation: "capability-run", cliArgs: { capability: capability.slug } };
|
|
2165
2089
|
}
|
|
2166
2090
|
const firstWorkflowStep = capability.config.workflow?.steps[0];
|
|
2167
2091
|
if (firstWorkflowStep) {
|
|
@@ -2172,36 +2096,6 @@ function resolveCapabilityExecution(capability, cwd = process.cwd()) {
|
|
|
2172
2096
|
const cliArgs = implementationDeclaresInput(implementation, "capability", cwd) ? { capability: capability.slug } : {};
|
|
2173
2097
|
return { implementation, cliArgs };
|
|
2174
2098
|
}
|
|
2175
|
-
function repositoryImplementationBinding(capabilityId, cwd) {
|
|
2176
|
-
try {
|
|
2177
|
-
return loadConfig(cwd).execution?.capabilityBindings[capabilityId];
|
|
2178
|
-
} catch {
|
|
2179
|
-
return void 0;
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
function readExternalImplementations(cwd) {
|
|
2183
|
-
const root = implementationsRoot(cwd);
|
|
2184
|
-
if (!fs6.existsSync(root)) return [];
|
|
2185
|
-
const definitions = [];
|
|
2186
|
-
for (const entry of fs6.readdirSync(root, { withFileTypes: true })) {
|
|
2187
|
-
if (!entry.isDirectory() || !isSafeName(entry.name)) continue;
|
|
2188
|
-
const definitionPath = path7.join(root, entry.name, "definition.json");
|
|
2189
|
-
if (!fs6.existsSync(definitionPath)) continue;
|
|
2190
|
-
try {
|
|
2191
|
-
const definition = JSON.parse(fs6.readFileSync(definitionPath, "utf-8"));
|
|
2192
|
-
definitions.push(definition);
|
|
2193
|
-
} catch {
|
|
2194
|
-
}
|
|
2195
|
-
}
|
|
2196
|
-
return definitions;
|
|
2197
|
-
}
|
|
2198
|
-
function canonical(value) {
|
|
2199
|
-
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
2200
|
-
if (value && typeof value === "object") {
|
|
2201
|
-
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(",")}}`;
|
|
2202
|
-
}
|
|
2203
|
-
return JSON.stringify(value);
|
|
2204
|
-
}
|
|
2205
2099
|
function implementationDeclaresInput(implementation, inputName, cwd = process.cwd()) {
|
|
2206
2100
|
const profilePath = resolveImplementation(implementation, getRuntimeProfileRootsForCwd(cwd));
|
|
2207
2101
|
if (!profilePath) return false;
|
|
@@ -2229,7 +2123,10 @@ function isCapabilityRoot(root) {
|
|
|
2229
2123
|
}
|
|
2230
2124
|
function implementationRuntimePath(root, name) {
|
|
2231
2125
|
const runtimePath = path7.join(root, name, "runtime.json");
|
|
2232
|
-
|
|
2126
|
+
if (fs6.existsSync(runtimePath)) return runtimePath;
|
|
2127
|
+
const internalProfilePath = path7.join(root, name, "profile.json");
|
|
2128
|
+
if (fs6.existsSync(internalProfilePath)) return internalProfilePath;
|
|
2129
|
+
return path7.join(root, name, CAPABILITY_PROFILE_FILE);
|
|
2233
2130
|
}
|
|
2234
2131
|
function isImplementationProfile(profilePath, requireImplementationProfile) {
|
|
2235
2132
|
if (!requireImplementationProfile) return true;
|
|
@@ -2336,9 +2233,7 @@ var PUBLIC_IMPLEMENTATION_ROLES;
|
|
|
2336
2233
|
var init_registry = __esm({
|
|
2337
2234
|
"src/registry.ts"() {
|
|
2338
2235
|
"use strict";
|
|
2339
|
-
init_implementation_resolution();
|
|
2340
2236
|
init_capabilityFolders();
|
|
2341
|
-
init_config();
|
|
2342
2237
|
init_definition_paths();
|
|
2343
2238
|
PUBLIC_IMPLEMENTATION_ROLES = /* @__PURE__ */ new Set(["primitive", "orchestrator", "container", "watch", "utility"]);
|
|
2344
2239
|
}
|
|
@@ -4931,7 +4826,7 @@ var init_subagents = __esm({
|
|
|
4931
4826
|
});
|
|
4932
4827
|
|
|
4933
4828
|
// src/profile.ts
|
|
4934
|
-
import { createHash as
|
|
4829
|
+
import { createHash as createHash3 } from "crypto";
|
|
4935
4830
|
import * as fs21 from "fs";
|
|
4936
4831
|
import * as path20 from "path";
|
|
4937
4832
|
function loadProfile(profilePath) {
|
|
@@ -4972,7 +4867,7 @@ function loadProfile(profilePath) {
|
|
|
4972
4867
|
implementation: execRef,
|
|
4973
4868
|
internal: typeof r.internal === "boolean" ? r.internal : base.internal,
|
|
4974
4869
|
public: typeof r.public === "boolean" ? r.public : base.public,
|
|
4975
|
-
capabilityKind:
|
|
4870
|
+
capabilityKind: parseCapabilityKind(r.capabilityKind) ?? base.capabilityKind,
|
|
4976
4871
|
slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : base.slug,
|
|
4977
4872
|
title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : base.title,
|
|
4978
4873
|
skills: parseStringArray2(r.skills) ?? base.skills,
|
|
@@ -4981,7 +4876,7 @@ function loadProfile(profilePath) {
|
|
|
4981
4876
|
describe: typeof r.describe === "string" ? r.describe : base.describe,
|
|
4982
4877
|
agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : base.agent,
|
|
4983
4878
|
capabilityTools: parseStringArray2(r.capabilityTools ?? r.capabilityTools ?? r.tools) ?? base.capabilityTools,
|
|
4984
|
-
capabilityToolMode:
|
|
4879
|
+
capabilityToolMode: parseCapabilityToolMode(profilePath, r.capabilityToolMode) ?? base.capabilityToolMode,
|
|
4985
4880
|
mentions: Array.isArray(r.mentions) ? r.mentions.map((m) => String(m).trim()).filter(Boolean) : base.mentions
|
|
4986
4881
|
};
|
|
4987
4882
|
}
|
|
@@ -5025,7 +4920,7 @@ function loadProfile(profilePath) {
|
|
|
5025
4920
|
implementation: void 0,
|
|
5026
4921
|
internal: typeof r.internal === "boolean" ? r.internal : void 0,
|
|
5027
4922
|
public: typeof r.public === "boolean" ? r.public : void 0,
|
|
5028
|
-
capabilityKind:
|
|
4923
|
+
capabilityKind: parseCapabilityKind(r.capabilityKind),
|
|
5029
4924
|
slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : void 0,
|
|
5030
4925
|
title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : void 0,
|
|
5031
4926
|
skills: parseStringArray2(r.skills),
|
|
@@ -5037,7 +4932,7 @@ function loadProfile(profilePath) {
|
|
|
5037
4932
|
agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : void 0,
|
|
5038
4933
|
// Locked-toolbox palette + mentions from folder-capability profile metadata.
|
|
5039
4934
|
capabilityTools: parseStringArray2(r.capabilityTools ?? r.capabilityTools ?? r.tools),
|
|
5040
|
-
capabilityToolMode:
|
|
4935
|
+
capabilityToolMode: parseCapabilityToolMode(profilePath, r.capabilityToolMode),
|
|
5041
4936
|
mentions: Array.isArray(r.mentions) ? r.mentions.map((m) => String(m).trim()).filter(Boolean) : void 0,
|
|
5042
4937
|
role,
|
|
5043
4938
|
kind,
|
|
@@ -5130,18 +5025,18 @@ function compileRuntimeDocument(runtimePath, document) {
|
|
|
5130
5025
|
agent: agentRef,
|
|
5131
5026
|
canonicalContract: {
|
|
5132
5027
|
capabilityId,
|
|
5133
|
-
capabilityRevision:
|
|
5028
|
+
capabilityRevision: createHash3("sha256").update(canonical(capability)).digest("hex"),
|
|
5134
5029
|
implementationId: String(implementation.id),
|
|
5135
|
-
implementationRevision:
|
|
5030
|
+
implementationRevision: createHash3("sha256").update(canonical(implementation)).digest("hex"),
|
|
5136
5031
|
inputSchema: capability.inputSchema,
|
|
5137
5032
|
outputSchema: capability.outputSchema
|
|
5138
5033
|
}
|
|
5139
5034
|
};
|
|
5140
5035
|
}
|
|
5141
|
-
function
|
|
5142
|
-
if (Array.isArray(value)) return `[${value.map(
|
|
5036
|
+
function canonical(value) {
|
|
5037
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
5143
5038
|
if (value && typeof value === "object") {
|
|
5144
|
-
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${
|
|
5039
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(",")}}`;
|
|
5145
5040
|
}
|
|
5146
5041
|
return JSON.stringify(value);
|
|
5147
5042
|
}
|
|
@@ -5156,7 +5051,7 @@ function readJsonObject(filePath, label) {
|
|
|
5156
5051
|
throw new ProfileError(filePath, `${label} is invalid: ${error instanceof Error ? error.message : String(error)}`);
|
|
5157
5052
|
}
|
|
5158
5053
|
}
|
|
5159
|
-
function
|
|
5054
|
+
function parseCapabilityToolMode(profilePath, raw) {
|
|
5160
5055
|
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
5161
5056
|
if (raw === "lock" || raw === "append") return raw;
|
|
5162
5057
|
throw new ProfileError(profilePath, `"capabilityToolMode" must be "lock" or "append"`);
|
|
@@ -5274,7 +5169,7 @@ function parseAuth(p, raw) {
|
|
|
5274
5169
|
});
|
|
5275
5170
|
return { methods };
|
|
5276
5171
|
}
|
|
5277
|
-
function
|
|
5172
|
+
function parseCapabilityKind(raw) {
|
|
5278
5173
|
return raw === "observe" || raw === "act" || raw === "verify" ? raw : void 0;
|
|
5279
5174
|
}
|
|
5280
5175
|
function parseInputs(p, raw) {
|
|
@@ -8227,9 +8122,9 @@ import * as fs27 from "fs";
|
|
|
8227
8122
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
8228
8123
|
const logs = goalRunLogs(data);
|
|
8229
8124
|
const existing = logs[goalId];
|
|
8230
|
-
const
|
|
8125
|
+
const path54 = existing?.path ?? goalRunLogPath(goalId, data);
|
|
8231
8126
|
logs[goalId] = {
|
|
8232
|
-
path:
|
|
8127
|
+
path: path54,
|
|
8233
8128
|
events: [...existing?.events ?? [], buildGoalRunLogEvent(data, goalId, event, at)]
|
|
8234
8129
|
};
|
|
8235
8130
|
}
|
|
@@ -9202,11 +9097,11 @@ function validateWorkflow(value, options = {}) {
|
|
|
9202
9097
|
function formatWorkflowValidationIssues(issues) {
|
|
9203
9098
|
return issues.map((entry) => `${entry.path}: ${entry.message}`);
|
|
9204
9099
|
}
|
|
9205
|
-
function validateDataMatch(value,
|
|
9100
|
+
function validateDataMatch(value, path54, issues, capabilityOutputs) {
|
|
9206
9101
|
if (value === void 0) return;
|
|
9207
9102
|
const match = asRecord2(value);
|
|
9208
9103
|
if (!match || Object.keys(match).length === 0) {
|
|
9209
|
-
issue(issues, "invalid_condition",
|
|
9104
|
+
issue(issues, "invalid_condition", path54, "workflow condition must contain at least one match");
|
|
9210
9105
|
return;
|
|
9211
9106
|
}
|
|
9212
9107
|
for (const [field, expected] of Object.entries(match)) {
|
|
@@ -9214,7 +9109,7 @@ function validateDataMatch(value, path52, issues, capabilityOutputs) {
|
|
|
9214
9109
|
issue(
|
|
9215
9110
|
issues,
|
|
9216
9111
|
"invalid_data_path",
|
|
9217
|
-
`${
|
|
9112
|
+
`${path54}.${field}`,
|
|
9218
9113
|
`workflow condition must read from facts, evidence, artifacts, result, workflow, or lastOutcome`
|
|
9219
9114
|
);
|
|
9220
9115
|
}
|
|
@@ -9222,12 +9117,12 @@ function validateDataMatch(value, path52, issues, capabilityOutputs) {
|
|
|
9222
9117
|
issue(
|
|
9223
9118
|
issues,
|
|
9224
9119
|
"undeclared_result_path",
|
|
9225
|
-
`${
|
|
9120
|
+
`${path54}.${field}`,
|
|
9226
9121
|
`workflow condition reads ${field}, but the source capability does not declare it`
|
|
9227
9122
|
);
|
|
9228
9123
|
}
|
|
9229
9124
|
if (!isComparable(expected)) {
|
|
9230
|
-
issue(issues, "invalid_condition_value", `${
|
|
9125
|
+
issue(issues, "invalid_condition_value", `${path54}.${field}`, "workflow condition value must be a JSON scalar");
|
|
9231
9126
|
}
|
|
9232
9127
|
}
|
|
9233
9128
|
}
|
|
@@ -9245,8 +9140,8 @@ function isComparable(value) {
|
|
|
9245
9140
|
if (value === null || ["string", "number", "boolean"].includes(typeof value)) return true;
|
|
9246
9141
|
return Array.isArray(value) && value.length > 0 && value.every((item) => isComparable(item) && !Array.isArray(item));
|
|
9247
9142
|
}
|
|
9248
|
-
function issue(issues, code,
|
|
9249
|
-
issues.push({ code, path:
|
|
9143
|
+
function issue(issues, code, path54, message) {
|
|
9144
|
+
issues.push({ code, path: path54, message });
|
|
9250
9145
|
}
|
|
9251
9146
|
var SAFE_NAME, SAFE_STEP_ID, SAFE_DATA_PATH, SUPPORTED_STEP_FIELDS, SUPPORTED_TRANSITION_FIELDS;
|
|
9252
9147
|
var init_workflowValidation = __esm({
|
|
@@ -9264,7 +9159,6 @@ var init_workflowValidation = __esm({
|
|
|
9264
9159
|
"target",
|
|
9265
9160
|
"targetFact",
|
|
9266
9161
|
"reason",
|
|
9267
|
-
"agent",
|
|
9268
9162
|
"cliArgs",
|
|
9269
9163
|
"inputs",
|
|
9270
9164
|
"next",
|
|
@@ -9293,6 +9187,8 @@ function normalizeWorkflowDefinition(value) {
|
|
|
9293
9187
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
9294
9188
|
const raw = value;
|
|
9295
9189
|
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
9190
|
+
const requestedAgent = typeof raw.agent === "string" ? raw.agent.trim() : "";
|
|
9191
|
+
const agent = /^[a-z][a-z0-9-]*$/.test(requestedAgent) ? requestedAgent : "kody";
|
|
9296
9192
|
const hasGraphConnections = Array.isArray(raw.steps) && raw.steps.some(
|
|
9297
9193
|
(step) => step && typeof step === "object" && !Array.isArray(step) && (step.next !== void 0 || step.inputs !== void 0)
|
|
9298
9194
|
);
|
|
@@ -9309,8 +9205,8 @@ function normalizeWorkflowDefinition(value) {
|
|
|
9309
9205
|
const capabilities = steps ? steps.map((step) => step.capability) : normalizeWorkflowCapabilities(raw.capabilities);
|
|
9310
9206
|
if (!name || capabilities.length === 0) return null;
|
|
9311
9207
|
return {
|
|
9312
|
-
version: 1,
|
|
9313
9208
|
name,
|
|
9209
|
+
agent,
|
|
9314
9210
|
capabilities,
|
|
9315
9211
|
...raw.runWithoutApproval === true ? { runWithoutApproval: true } : {},
|
|
9316
9212
|
...steps ? { steps } : {},
|
|
@@ -9324,7 +9220,7 @@ function readWorkflowDefinition(_config, cwd, id) {
|
|
|
9324
9220
|
const relativePath = workflowDefinitionPath(id);
|
|
9325
9221
|
const candidates = [
|
|
9326
9222
|
path26.join(root, ".kody-engine", "runtime", relativePath),
|
|
9327
|
-
path26.join(root,
|
|
9223
|
+
path26.join(definitionsRoot(root), relativePath)
|
|
9328
9224
|
];
|
|
9329
9225
|
for (const filePath of candidates) {
|
|
9330
9226
|
if (!fs29.existsSync(filePath)) continue;
|
|
@@ -9346,7 +9242,8 @@ function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDef
|
|
|
9346
9242
|
config: {
|
|
9347
9243
|
action: id,
|
|
9348
9244
|
workflow: workflowDefinitionToConfig(workflow),
|
|
9349
|
-
describe: workflow.name
|
|
9245
|
+
describe: workflow.name,
|
|
9246
|
+
agent: workflow.agent
|
|
9350
9247
|
}
|
|
9351
9248
|
};
|
|
9352
9249
|
}
|
|
@@ -9381,6 +9278,7 @@ var init_workflowDefinitions = __esm({
|
|
|
9381
9278
|
"src/workflowDefinitions.ts"() {
|
|
9382
9279
|
"use strict";
|
|
9383
9280
|
init_capabilityFolders();
|
|
9281
|
+
init_definition_paths();
|
|
9384
9282
|
init_workflowValidation();
|
|
9385
9283
|
WORKFLOW_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{0,79}$/;
|
|
9386
9284
|
CAPABILITY_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,79}$/;
|
|
@@ -9513,15 +9411,15 @@ var init_backendStateBackend = __esm({
|
|
|
9513
9411
|
this.jobsDir = opts.jobsDir.replace(/\/+$/, "");
|
|
9514
9412
|
}
|
|
9515
9413
|
async load(slug) {
|
|
9516
|
-
const
|
|
9414
|
+
const path54 = stateFilePath(this.jobsDir, slug);
|
|
9517
9415
|
const loaded = await createStateBackendFromEnv().get(this.tenantId, `capabilities/${slug}`, "job-state");
|
|
9518
9416
|
if (!loaded) {
|
|
9519
|
-
return { path:
|
|
9417
|
+
return { path: path54, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
9520
9418
|
}
|
|
9521
9419
|
if (!isStateEnvelope(loaded.doc)) {
|
|
9522
9420
|
throw new Error(`BackendStateBackend: capabilities/${slug} is not a StateEnvelope`);
|
|
9523
9421
|
}
|
|
9524
|
-
return { path:
|
|
9422
|
+
return { path: path54, handle: loaded.updatedAt, state: loaded.doc, created: false };
|
|
9525
9423
|
}
|
|
9526
9424
|
async save(loaded, next) {
|
|
9527
9425
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) return false;
|
|
@@ -13524,7 +13422,7 @@ var init_triggerDispatcher = __esm({
|
|
|
13524
13422
|
});
|
|
13525
13423
|
|
|
13526
13424
|
// src/goal/policyResolver.ts
|
|
13527
|
-
import { createHash as
|
|
13425
|
+
import { createHash as createHash4 } from "crypto";
|
|
13528
13426
|
function resolveDispatchPolicy(input) {
|
|
13529
13427
|
const operation = input.catalog.operations.get(input.owner.definition.operationId);
|
|
13530
13428
|
if (!operation) throw new Error(`Dispatch blocked: Operation "${input.owner.definition.operationId}" is unresolved`);
|
|
@@ -13542,7 +13440,7 @@ function resolveDispatchPolicy(input) {
|
|
|
13542
13440
|
const snapshotValue = { policy, constraints };
|
|
13543
13441
|
return {
|
|
13544
13442
|
snapshot: {
|
|
13545
|
-
hash:
|
|
13443
|
+
hash: createHash4("sha256").update(stableJson(snapshotValue)).digest("hex"),
|
|
13546
13444
|
...snapshotValue
|
|
13547
13445
|
},
|
|
13548
13446
|
operation,
|
|
@@ -15343,17 +15241,103 @@ var init_loadCapabilityState = __esm({
|
|
|
15343
15241
|
}
|
|
15344
15242
|
});
|
|
15345
15243
|
|
|
15244
|
+
// src/scripts/loadSimpleCapability.ts
|
|
15245
|
+
import * as fs39 from "fs";
|
|
15246
|
+
import * as path36 from "path";
|
|
15247
|
+
function listFiles(root) {
|
|
15248
|
+
if (!fs39.existsSync(root)) return [];
|
|
15249
|
+
const files = [];
|
|
15250
|
+
const visit = (dir) => {
|
|
15251
|
+
for (const entry of fs39.readdirSync(dir, { withFileTypes: true })) {
|
|
15252
|
+
const absolute = path36.join(dir, entry.name);
|
|
15253
|
+
if (entry.isSymbolicLink()) continue;
|
|
15254
|
+
if (entry.isDirectory()) visit(absolute);
|
|
15255
|
+
else if (entry.isFile()) files.push(path36.relative(root, absolute));
|
|
15256
|
+
}
|
|
15257
|
+
};
|
|
15258
|
+
visit(root);
|
|
15259
|
+
return files.sort();
|
|
15260
|
+
}
|
|
15261
|
+
var loadSimpleCapability;
|
|
15262
|
+
var init_loadSimpleCapability = __esm({
|
|
15263
|
+
"src/scripts/loadSimpleCapability.ts"() {
|
|
15264
|
+
"use strict";
|
|
15265
|
+
init_definition_paths();
|
|
15266
|
+
init_capabilityFolders();
|
|
15267
|
+
loadSimpleCapability = async (ctx) => {
|
|
15268
|
+
const slug = typeof ctx.args.capability === "string" ? ctx.args.capability.trim() : "";
|
|
15269
|
+
if (!/^[a-z][a-z0-9-]*$/.test(slug)) {
|
|
15270
|
+
throw new Error("capability-run requires a valid capability slug");
|
|
15271
|
+
}
|
|
15272
|
+
const capability = readCapabilityFolder(capabilitiesRoot(ctx.cwd), slug);
|
|
15273
|
+
if (!capability) {
|
|
15274
|
+
throw new Error(`Capability "${slug}" is not a valid simple capability folder`);
|
|
15275
|
+
}
|
|
15276
|
+
const contract = capability.rawProfile.contract;
|
|
15277
|
+
const toolRoot = path36.join(capability.dir, "tools");
|
|
15278
|
+
const skillRoot = path36.join(capability.dir, "skills");
|
|
15279
|
+
const toolFiles = listFiles(toolRoot);
|
|
15280
|
+
const skillFiles = listFiles(skillRoot);
|
|
15281
|
+
const supplied = ctx.args.input;
|
|
15282
|
+
let input = supplied;
|
|
15283
|
+
if (typeof supplied === "string") {
|
|
15284
|
+
try {
|
|
15285
|
+
input = JSON.parse(supplied);
|
|
15286
|
+
} catch {
|
|
15287
|
+
input = supplied;
|
|
15288
|
+
}
|
|
15289
|
+
}
|
|
15290
|
+
ctx.data.jobCapability = slug;
|
|
15291
|
+
ctx.data.capabilityInput = input;
|
|
15292
|
+
ctx.data.capabilityContract = contract;
|
|
15293
|
+
ctx.data.prompt = [
|
|
15294
|
+
capability.rawBody.trim(),
|
|
15295
|
+
"",
|
|
15296
|
+
"## Input",
|
|
15297
|
+
"",
|
|
15298
|
+
"```json",
|
|
15299
|
+
JSON.stringify({ [contract.input.name]: input }, null, 2),
|
|
15300
|
+
"```",
|
|
15301
|
+
"",
|
|
15302
|
+
"Return one JSON value matching the output contract:",
|
|
15303
|
+
"",
|
|
15304
|
+
"```json",
|
|
15305
|
+
JSON.stringify({ [contract.output.name]: contract.output.schema }, null, 2),
|
|
15306
|
+
"```",
|
|
15307
|
+
...skillFiles.length ? [
|
|
15308
|
+
"",
|
|
15309
|
+
"## Skills",
|
|
15310
|
+
"",
|
|
15311
|
+
...skillFiles.flatMap((file) => [
|
|
15312
|
+
`### ${file}`,
|
|
15313
|
+
"",
|
|
15314
|
+
fs39.readFileSync(path36.join(skillRoot, file), "utf-8"),
|
|
15315
|
+
""
|
|
15316
|
+
])
|
|
15317
|
+
] : [],
|
|
15318
|
+
...toolFiles.length ? [
|
|
15319
|
+
"",
|
|
15320
|
+
"## Tools",
|
|
15321
|
+
"",
|
|
15322
|
+
"Inspect or run these capability-owned files when needed:",
|
|
15323
|
+
...toolFiles.map((file) => `- ${path36.join(toolRoot, file)}`)
|
|
15324
|
+
] : []
|
|
15325
|
+
].join("\n");
|
|
15326
|
+
};
|
|
15327
|
+
}
|
|
15328
|
+
});
|
|
15329
|
+
|
|
15346
15330
|
// src/companyIntent.ts
|
|
15347
15331
|
function isCompanyIntentId(value) {
|
|
15348
15332
|
return SLUG_RE2.test(value);
|
|
15349
15333
|
}
|
|
15350
|
-
function normalizeCompanyIntent(
|
|
15334
|
+
function normalizeCompanyIntent(path54, raw) {
|
|
15351
15335
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
15352
|
-
throw new Error(`${
|
|
15336
|
+
throw new Error(`${path54}: intent must be JSON object`);
|
|
15353
15337
|
}
|
|
15354
15338
|
const input = raw;
|
|
15355
15339
|
const id = stringField4(input.id);
|
|
15356
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${
|
|
15340
|
+
if (!id || !isCompanyIntentId(id)) throw new Error(`${path54}: invalid intent id`);
|
|
15357
15341
|
const createdAt = stringField4(input.createdAt) || nowIso();
|
|
15358
15342
|
const updatedAt = stringField4(input.updatedAt) || createdAt;
|
|
15359
15343
|
const description = stringField4(input.description);
|
|
@@ -15644,8 +15628,8 @@ var init_loadIssueStateComment = __esm({
|
|
|
15644
15628
|
});
|
|
15645
15629
|
|
|
15646
15630
|
// src/scripts/loadJobFromFile.ts
|
|
15647
|
-
import * as
|
|
15648
|
-
import * as
|
|
15631
|
+
import * as fs40 from "fs";
|
|
15632
|
+
import * as path37 from "path";
|
|
15649
15633
|
function parseJobFile(raw, slug) {
|
|
15650
15634
|
let stripped = raw;
|
|
15651
15635
|
if (stripped.startsWith("---\n")) {
|
|
@@ -15684,10 +15668,10 @@ var init_loadJobFromFile = __esm({
|
|
|
15684
15668
|
if (!slug) {
|
|
15685
15669
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
15686
15670
|
}
|
|
15687
|
-
const capability = resolveCapabilityFolder(slug,
|
|
15671
|
+
const capability = resolveCapabilityFolder(slug, path37.resolve(ctx.cwd, jobsDir));
|
|
15688
15672
|
if (!capability) {
|
|
15689
15673
|
throw new Error(
|
|
15690
|
-
`loadJobFromFile: capability folder not found or incomplete: ${
|
|
15674
|
+
`loadJobFromFile: capability folder not found or incomplete: ${path37.resolve(ctx.cwd, jobsDir, slug)}`
|
|
15691
15675
|
);
|
|
15692
15676
|
}
|
|
15693
15677
|
const { title, body, config } = capability;
|
|
@@ -15697,12 +15681,12 @@ var init_loadJobFromFile = __esm({
|
|
|
15697
15681
|
let agentIdentity = "";
|
|
15698
15682
|
if (agentSlug) {
|
|
15699
15683
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
15700
|
-
if (!
|
|
15684
|
+
if (!fs40.existsSync(agentPath)) {
|
|
15701
15685
|
throw new Error(
|
|
15702
15686
|
`loadJobFromFile: capability '${slug}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
15703
15687
|
);
|
|
15704
15688
|
}
|
|
15705
|
-
const agentRaw =
|
|
15689
|
+
const agentRaw = fs40.readFileSync(agentPath, "utf-8");
|
|
15706
15690
|
const parsed = parseJobFile(agentRaw, agentSlug);
|
|
15707
15691
|
agentTitle = parsed.title;
|
|
15708
15692
|
agentIdentity = parsed.body;
|
|
@@ -15782,13 +15766,13 @@ ${truncate2(issue2.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
15782
15766
|
});
|
|
15783
15767
|
|
|
15784
15768
|
// src/scripts/kodyVariables.ts
|
|
15785
|
-
import * as
|
|
15786
|
-
import * as
|
|
15769
|
+
import * as fs41 from "fs";
|
|
15770
|
+
import * as path38 from "path";
|
|
15787
15771
|
function readKodyVariables(cwd) {
|
|
15788
|
-
const full =
|
|
15772
|
+
const full = path38.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
15789
15773
|
let raw;
|
|
15790
15774
|
try {
|
|
15791
|
-
raw =
|
|
15775
|
+
raw = fs41.readFileSync(full, "utf-8");
|
|
15792
15776
|
} catch {
|
|
15793
15777
|
return {};
|
|
15794
15778
|
}
|
|
@@ -15813,9 +15797,9 @@ var init_kodyVariables = __esm({
|
|
|
15813
15797
|
});
|
|
15814
15798
|
|
|
15815
15799
|
// src/backendVault.ts
|
|
15816
|
-
import { createDecipheriv, createHash as
|
|
15800
|
+
import { createDecipheriv, createHash as createHash5 } from "crypto";
|
|
15817
15801
|
function cacheKey(owner, repo, masterKey) {
|
|
15818
|
-
const keyHash =
|
|
15802
|
+
const keyHash = createHash5("sha256").update(masterKey).digest("hex").slice(0, 16);
|
|
15819
15803
|
return `${owner}/${repo}:${keyHash}`.toLowerCase();
|
|
15820
15804
|
}
|
|
15821
15805
|
function decryptVault(payload, masterKey) {
|
|
@@ -15964,8 +15948,8 @@ var init_runtimeSecrets = __esm({
|
|
|
15964
15948
|
});
|
|
15965
15949
|
|
|
15966
15950
|
// src/scripts/loadQaContext.ts
|
|
15967
|
-
import * as
|
|
15968
|
-
import * as
|
|
15951
|
+
import * as fs42 from "fs";
|
|
15952
|
+
import * as path39 from "path";
|
|
15969
15953
|
function parseSlugList(value) {
|
|
15970
15954
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
15971
15955
|
return inner.split(",").map(
|
|
@@ -15994,18 +15978,18 @@ function readProfileAgents(raw) {
|
|
|
15994
15978
|
return { agent: agent ?? legacy ?? ["kody"], body };
|
|
15995
15979
|
}
|
|
15996
15980
|
function readProfile(cwd) {
|
|
15997
|
-
const dir =
|
|
15998
|
-
if (!
|
|
15981
|
+
const dir = path39.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
15982
|
+
if (!fs42.existsSync(dir)) return "";
|
|
15999
15983
|
let entries;
|
|
16000
15984
|
try {
|
|
16001
|
-
entries =
|
|
15985
|
+
entries = fs42.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
16002
15986
|
} catch {
|
|
16003
15987
|
return "";
|
|
16004
15988
|
}
|
|
16005
15989
|
const blocks = [];
|
|
16006
15990
|
for (const file of entries) {
|
|
16007
15991
|
try {
|
|
16008
|
-
const raw =
|
|
15992
|
+
const raw = fs42.readFileSync(path39.join(dir, file), "utf-8");
|
|
16009
15993
|
const { agent, body } = readProfileAgents(raw);
|
|
16010
15994
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
16011
15995
|
blocks.push(`## ${file}
|
|
@@ -16054,8 +16038,8 @@ var init_loadQaContext = __esm({
|
|
|
16054
16038
|
});
|
|
16055
16039
|
|
|
16056
16040
|
// src/taskContext.ts
|
|
16057
|
-
import * as
|
|
16058
|
-
import * as
|
|
16041
|
+
import * as fs43 from "fs";
|
|
16042
|
+
import * as path40 from "path";
|
|
16059
16043
|
function buildTaskContext(args) {
|
|
16060
16044
|
return {
|
|
16061
16045
|
schemaVersion: TASK_CONTEXT_SCHEMA_VERSION,
|
|
@@ -16071,9 +16055,9 @@ function buildTaskContext(args) {
|
|
|
16071
16055
|
function persistTaskContext(cwd, ctx) {
|
|
16072
16056
|
try {
|
|
16073
16057
|
const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
|
|
16074
|
-
|
|
16075
|
-
const file =
|
|
16076
|
-
|
|
16058
|
+
fs43.mkdirSync(dir, { recursive: true });
|
|
16059
|
+
const file = path40.join(dir, "task-context.json");
|
|
16060
|
+
fs43.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
|
|
16077
16061
|
`);
|
|
16078
16062
|
return file;
|
|
16079
16063
|
} catch (err) {
|
|
@@ -16464,7 +16448,7 @@ var init_notifyTerminal = __esm({
|
|
|
16464
16448
|
});
|
|
16465
16449
|
|
|
16466
16450
|
// src/scripts/openAgencyModelReviewPr.ts
|
|
16467
|
-
import { createHash as
|
|
16451
|
+
import { createHash as createHash6 } from "crypto";
|
|
16468
16452
|
function parseAgencyModelProposal(raw) {
|
|
16469
16453
|
const text2 = raw.trim();
|
|
16470
16454
|
const jsonText = (text2.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/i)?.[1] ?? text2).trim();
|
|
@@ -16500,23 +16484,23 @@ function parseAgencyModelProposal(raw) {
|
|
|
16500
16484
|
function normalizeBundleFiles(bundle) {
|
|
16501
16485
|
const seen = /* @__PURE__ */ new Set();
|
|
16502
16486
|
return bundle.files.map((file, index) => {
|
|
16503
|
-
const
|
|
16504
|
-
const parts =
|
|
16505
|
-
if (!
|
|
16487
|
+
const path54 = file.path.replace(/^\/+/, "");
|
|
16488
|
+
const parts = path54.split("/");
|
|
16489
|
+
if (!path54 || file.path.startsWith("/") || file.path.includes("\\") || parts.some((part) => !part || part === "." || part === "..")) {
|
|
16506
16490
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is unsafe`);
|
|
16507
16491
|
}
|
|
16508
16492
|
if (!/^(agents\/[^/]+\.md|capabilities\/[^/]+\/.+|goals\/(?:templates\/)?[^/]+\/.+|workflows\/[^/]+\.json)$/.test(
|
|
16509
|
-
|
|
16493
|
+
path54
|
|
16510
16494
|
)) {
|
|
16511
16495
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is not a supported definition path`);
|
|
16512
16496
|
}
|
|
16513
|
-
if (seen.has(
|
|
16514
|
-
seen.add(
|
|
16515
|
-
return { path:
|
|
16497
|
+
if (seen.has(path54)) throw new Error(`openAgencyModelReviewPr: duplicate generated file path: ${path54}`);
|
|
16498
|
+
seen.add(path54);
|
|
16499
|
+
return { path: path54, content: file.content.replace(/\r\n?/g, "\n") };
|
|
16516
16500
|
});
|
|
16517
16501
|
}
|
|
16518
16502
|
function buildProposalId(issueNumber, bundle, sourceLabel) {
|
|
16519
|
-
const digest =
|
|
16503
|
+
const digest = createHash6("sha256").update(JSON.stringify({ issueNumber, sourceLabel, title: bundle.title, files: normalizeBundleFiles(bundle) })).digest("hex").slice(0, 16);
|
|
16520
16504
|
return `issue-${issueNumber}-${digest}`;
|
|
16521
16505
|
}
|
|
16522
16506
|
function isDryRun(ctx) {
|
|
@@ -17456,9 +17440,9 @@ var init_postResearchComment = __esm({
|
|
|
17456
17440
|
});
|
|
17457
17441
|
|
|
17458
17442
|
// src/scripts/prepareBrowserAuth.ts
|
|
17459
|
-
import * as
|
|
17443
|
+
import * as fs44 from "fs";
|
|
17460
17444
|
import * as os6 from "os";
|
|
17461
|
-
import * as
|
|
17445
|
+
import * as path41 from "path";
|
|
17462
17446
|
function appendAuthMessage(ctx, message) {
|
|
17463
17447
|
const current = typeof ctx.data.qaAuthBlock === "string" ? ctx.data.qaAuthBlock.trim() : "";
|
|
17464
17448
|
ctx.data.qaAuthBlock = current ? `${current}
|
|
@@ -17497,9 +17481,9 @@ async function githubJson(url, token) {
|
|
|
17497
17481
|
return await response.json();
|
|
17498
17482
|
}
|
|
17499
17483
|
function writeKodyStorageState(input) {
|
|
17500
|
-
const directory =
|
|
17501
|
-
|
|
17502
|
-
const file =
|
|
17484
|
+
const directory = fs44.mkdtempSync(path41.join(os6.tmpdir(), "kody-browser-auth-"));
|
|
17485
|
+
fs44.chmodSync(directory, 448);
|
|
17486
|
+
const file = path41.join(directory, "storage-state.json");
|
|
17503
17487
|
const now = Date.now();
|
|
17504
17488
|
const repoEntry = {
|
|
17505
17489
|
repoUrl: input.repoUrl,
|
|
@@ -17529,7 +17513,7 @@ function writeKodyStorageState(input) {
|
|
|
17529
17513
|
}
|
|
17530
17514
|
]
|
|
17531
17515
|
};
|
|
17532
|
-
|
|
17516
|
+
fs44.writeFileSync(file, JSON.stringify(storageState), { mode: 384 });
|
|
17533
17517
|
return { directory, file };
|
|
17534
17518
|
}
|
|
17535
17519
|
function configurePlaywright(profile, storageStatePath) {
|
|
@@ -17611,7 +17595,7 @@ async function prepareMethod(ctx, profile, method) {
|
|
|
17611
17595
|
configurePlaywright(profile, state.file);
|
|
17612
17596
|
const authDirectory = state.directory;
|
|
17613
17597
|
registerRuntimeCleanup(ctx, () => {
|
|
17614
|
-
|
|
17598
|
+
fs44.rmSync(authDirectory, { recursive: true, force: true });
|
|
17615
17599
|
});
|
|
17616
17600
|
appendAuthMessage(
|
|
17617
17601
|
ctx,
|
|
@@ -17619,7 +17603,7 @@ async function prepareMethod(ctx, profile, method) {
|
|
|
17619
17603
|
);
|
|
17620
17604
|
return true;
|
|
17621
17605
|
} catch (error) {
|
|
17622
|
-
if (state)
|
|
17606
|
+
if (state) fs44.rmSync(state.directory, { recursive: true, force: true });
|
|
17623
17607
|
const reason = error instanceof Error ? error.message : String(error);
|
|
17624
17608
|
appendAuthMessage(
|
|
17625
17609
|
ctx,
|
|
@@ -17732,9 +17716,9 @@ function latestResult(raw, agentResult) {
|
|
|
17732
17716
|
function recordField4(value) {
|
|
17733
17717
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
17734
17718
|
}
|
|
17735
|
-
function resolveDotted(root,
|
|
17736
|
-
if (!
|
|
17737
|
-
return
|
|
17719
|
+
function resolveDotted(root, path54) {
|
|
17720
|
+
if (!path54) return void 0;
|
|
17721
|
+
return path54.split(".").reduce((value, key) => recordField4(value)?.[key], root);
|
|
17738
17722
|
}
|
|
17739
17723
|
function stringValue4(value) {
|
|
17740
17724
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
@@ -18588,9 +18572,9 @@ var init_runFlow = __esm({
|
|
|
18588
18572
|
});
|
|
18589
18573
|
|
|
18590
18574
|
// src/scripts/previewBuildHelpers.ts
|
|
18591
|
-
import { createDecipheriv as createDecipheriv2, createHash as
|
|
18575
|
+
import { createDecipheriv as createDecipheriv2, createHash as createHash7, hkdfSync as hkdfSync2 } from "crypto";
|
|
18592
18576
|
function shortHash(s) {
|
|
18593
|
-
return
|
|
18577
|
+
return createHash7("sha256").update(s).digest("hex").slice(0, 6);
|
|
18594
18578
|
}
|
|
18595
18579
|
function previewAppName(repo, pr) {
|
|
18596
18580
|
const [owner, name] = repo.split("/");
|
|
@@ -18623,7 +18607,7 @@ function formatPreviewComment(args) {
|
|
|
18623
18607
|
].join("\n");
|
|
18624
18608
|
}
|
|
18625
18609
|
function defaultImageTag(repo, ref) {
|
|
18626
|
-
return
|
|
18610
|
+
return createHash7("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
|
|
18627
18611
|
}
|
|
18628
18612
|
var init_previewBuildHelpers = __esm({
|
|
18629
18613
|
"src/scripts/previewBuildHelpers.ts"() {
|
|
@@ -18718,12 +18702,12 @@ fi
|
|
|
18718
18702
|
|
|
18719
18703
|
// src/scripts/runPreviewBuild.ts
|
|
18720
18704
|
import { copyFile, writeFile } from "fs/promises";
|
|
18721
|
-
import * as
|
|
18705
|
+
import * as path42 from "path";
|
|
18722
18706
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
18723
18707
|
function bundledDockerfilePath(mode) {
|
|
18724
|
-
const here =
|
|
18708
|
+
const here = path42.dirname(fileURLToPath2(import.meta.url));
|
|
18725
18709
|
const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
|
|
18726
|
-
return
|
|
18710
|
+
return path42.join(here, "preview-build-templates", file);
|
|
18727
18711
|
}
|
|
18728
18712
|
function required(name) {
|
|
18729
18713
|
const v = (process.env[name] ?? "").trim();
|
|
@@ -18958,10 +18942,10 @@ var init_runPreviewBuild = __esm({
|
|
|
18958
18942
|
console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
|
|
18959
18943
|
if (Object.keys(buildEnv).length > 0) {
|
|
18960
18944
|
const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
|
|
18961
|
-
await writeFile(
|
|
18945
|
+
await writeFile(path42.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
|
|
18962
18946
|
`, "utf8");
|
|
18963
18947
|
}
|
|
18964
|
-
const consumerDockerfile =
|
|
18948
|
+
const consumerDockerfile = path42.join(ctx.cwd, "Dockerfile.preview");
|
|
18965
18949
|
const { stat } = await import("fs/promises");
|
|
18966
18950
|
let hasConsumerDockerfile = false;
|
|
18967
18951
|
try {
|
|
@@ -19145,8 +19129,8 @@ var init_tickShellRunner = __esm({
|
|
|
19145
19129
|
});
|
|
19146
19130
|
|
|
19147
19131
|
// src/scripts/runScheduledImplementationTick.ts
|
|
19148
|
-
import * as
|
|
19149
|
-
import * as
|
|
19132
|
+
import * as fs45 from "fs";
|
|
19133
|
+
import * as path43 from "path";
|
|
19150
19134
|
var runScheduledImplementationTick;
|
|
19151
19135
|
var init_runScheduledImplementationTick = __esm({
|
|
19152
19136
|
"src/scripts/runScheduledImplementationTick.ts"() {
|
|
@@ -19167,14 +19151,14 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
19167
19151
|
ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
19168
19152
|
return;
|
|
19169
19153
|
}
|
|
19170
|
-
const capability = resolveCapabilityFolder(slug,
|
|
19154
|
+
const capability = resolveCapabilityFolder(slug, path43.resolve(ctx.cwd, jobsDir));
|
|
19171
19155
|
if (!capability) {
|
|
19172
19156
|
ctx.output.exitCode = 99;
|
|
19173
19157
|
ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug} (searched ${jobsDir} and company store)`;
|
|
19174
19158
|
return;
|
|
19175
19159
|
}
|
|
19176
|
-
const shellPath =
|
|
19177
|
-
if (!
|
|
19160
|
+
const shellPath = path43.join(profile.dir, shell);
|
|
19161
|
+
if (!fs45.existsSync(shellPath)) {
|
|
19178
19162
|
ctx.output.exitCode = 99;
|
|
19179
19163
|
ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
19180
19164
|
return;
|
|
@@ -19205,8 +19189,8 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
19205
19189
|
});
|
|
19206
19190
|
|
|
19207
19191
|
// src/scripts/runTickScript.ts
|
|
19208
|
-
import * as
|
|
19209
|
-
import * as
|
|
19192
|
+
import * as fs46 from "fs";
|
|
19193
|
+
import * as path44 from "path";
|
|
19210
19194
|
var runTickScript;
|
|
19211
19195
|
var init_runTickScript = __esm({
|
|
19212
19196
|
"src/scripts/runTickScript.ts"() {
|
|
@@ -19226,10 +19210,10 @@ var init_runTickScript = __esm({
|
|
|
19226
19210
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
19227
19211
|
return;
|
|
19228
19212
|
}
|
|
19229
|
-
const capability = readCapabilityFolder(
|
|
19213
|
+
const capability = readCapabilityFolder(path44.resolve(ctx.cwd, jobsDir), slug);
|
|
19230
19214
|
if (!capability) {
|
|
19231
19215
|
ctx.output.exitCode = 99;
|
|
19232
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${
|
|
19216
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path44.resolve(ctx.cwd, jobsDir, slug)}`;
|
|
19233
19217
|
return;
|
|
19234
19218
|
}
|
|
19235
19219
|
const tickScript = capability.config.tickScript;
|
|
@@ -19238,8 +19222,8 @@ var init_runTickScript = __esm({
|
|
|
19238
19222
|
ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
19239
19223
|
return;
|
|
19240
19224
|
}
|
|
19241
|
-
const scriptPath =
|
|
19242
|
-
if (!
|
|
19225
|
+
const scriptPath = path44.isAbsolute(tickScript) ? tickScript : path44.join(ctx.cwd, tickScript);
|
|
19226
|
+
if (!fs46.existsSync(scriptPath)) {
|
|
19243
19227
|
ctx.output.exitCode = 99;
|
|
19244
19228
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
19245
19229
|
return;
|
|
@@ -19521,7 +19505,7 @@ var init_syncFlow = __esm({
|
|
|
19521
19505
|
});
|
|
19522
19506
|
|
|
19523
19507
|
// src/scripts/validateAgencyModelProposal.ts
|
|
19524
|
-
import * as
|
|
19508
|
+
import * as path45 from "path";
|
|
19525
19509
|
function validateModelBundle(bundle, expectedKind, options = {}) {
|
|
19526
19510
|
const failures = [];
|
|
19527
19511
|
validateOneModel(bundle.model, bundle.files, "model", true, failures, expectedKind, options);
|
|
@@ -19847,7 +19831,7 @@ var init_validateAgencyModelProposal = __esm({
|
|
|
19847
19831
|
const bundle = parseAgencyModelProposal(raw);
|
|
19848
19832
|
const expectedKind = readExpectedModelKind(args);
|
|
19849
19833
|
const failures = validateModelBundle(bundle, expectedKind, {
|
|
19850
|
-
capabilityRoot:
|
|
19834
|
+
capabilityRoot: path45.join(ctx.cwd, ".kody", "capabilities")
|
|
19851
19835
|
});
|
|
19852
19836
|
if (failures.length > 0) {
|
|
19853
19837
|
throw new Error(`validateAgencyModelProposal: ${failures.join("; ")}`);
|
|
@@ -20398,7 +20382,7 @@ var init_warmupMcp = __esm({
|
|
|
20398
20382
|
});
|
|
20399
20383
|
|
|
20400
20384
|
// src/scripts/writeAgentRunSummary.ts
|
|
20401
|
-
import * as
|
|
20385
|
+
import * as fs47 from "fs";
|
|
20402
20386
|
var writeAgentRunSummary;
|
|
20403
20387
|
var init_writeAgentRunSummary = __esm({
|
|
20404
20388
|
"src/scripts/writeAgentRunSummary.ts"() {
|
|
@@ -20424,7 +20408,7 @@ var init_writeAgentRunSummary = __esm({
|
|
|
20424
20408
|
if (reason) lines.push(`- **Reason:** ${reason}`);
|
|
20425
20409
|
lines.push("");
|
|
20426
20410
|
try {
|
|
20427
|
-
|
|
20411
|
+
fs47.appendFileSync(summaryPath, `${lines.join("\n")}
|
|
20428
20412
|
`);
|
|
20429
20413
|
} catch {
|
|
20430
20414
|
}
|
|
@@ -20572,6 +20556,7 @@ var init_scripts = __esm({
|
|
|
20572
20556
|
init_initFlow();
|
|
20573
20557
|
init_loadAgentAdhoc();
|
|
20574
20558
|
init_loadCapabilityState();
|
|
20559
|
+
init_loadSimpleCapability();
|
|
20575
20560
|
init_loadCompanyIntents();
|
|
20576
20561
|
init_loadCompanyPortfolio();
|
|
20577
20562
|
init_loadConventions();
|
|
@@ -20656,6 +20641,7 @@ var init_scripts = __esm({
|
|
|
20656
20641
|
loadIssueStateComment,
|
|
20657
20642
|
loadJobFromFile,
|
|
20658
20643
|
loadCapabilityState,
|
|
20644
|
+
loadSimpleCapability,
|
|
20659
20645
|
loadCompanyIntents,
|
|
20660
20646
|
loadCompanyPortfolio,
|
|
20661
20647
|
loadAgentAdhoc,
|
|
@@ -20752,17 +20738,17 @@ var init_scripts = __esm({
|
|
|
20752
20738
|
});
|
|
20753
20739
|
|
|
20754
20740
|
// src/stateWorkspace.ts
|
|
20755
|
-
import * as
|
|
20756
|
-
import * as
|
|
20741
|
+
import * as fs48 from "fs";
|
|
20742
|
+
import * as path46 from "path";
|
|
20757
20743
|
function tenantId(config) {
|
|
20758
20744
|
const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
|
|
20759
20745
|
const repo = config.github?.repo?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
|
|
20760
20746
|
return owner && repo ? `${owner}/${repo}` : null;
|
|
20761
20747
|
}
|
|
20762
20748
|
function writeRuntimeFile(cwd, relativePath, content) {
|
|
20763
|
-
const target =
|
|
20764
|
-
|
|
20765
|
-
|
|
20749
|
+
const target = path46.join(cwd, RUNTIME_ROOT, relativePath);
|
|
20750
|
+
fs48.mkdirSync(path46.dirname(target), { recursive: true });
|
|
20751
|
+
fs48.writeFileSync(target, content, "utf8");
|
|
20766
20752
|
}
|
|
20767
20753
|
function record(value) {
|
|
20768
20754
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -20827,11 +20813,11 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
|
|
|
20827
20813
|
throw new Error("Kody backend access is required for runtime workspace documents");
|
|
20828
20814
|
return;
|
|
20829
20815
|
}
|
|
20830
|
-
const key = `${
|
|
20816
|
+
const key = `${path46.resolve(cwd)}|${tenant}`;
|
|
20831
20817
|
if (hydratedWorkspaces.has(key)) return;
|
|
20832
20818
|
const backend = backendOverride ?? createStateBackendFromEnv();
|
|
20833
|
-
const root =
|
|
20834
|
-
|
|
20819
|
+
const root = path46.join(cwd, RUNTIME_ROOT);
|
|
20820
|
+
fs48.rmSync(root, { recursive: true, force: true });
|
|
20835
20821
|
await Promise.all([
|
|
20836
20822
|
hydratePrefix(backend, tenant, cwd, "context:"),
|
|
20837
20823
|
hydratePrefix(backend, tenant, cwd, "memory:"),
|
|
@@ -20847,7 +20833,7 @@ var init_stateWorkspace = __esm({
|
|
|
20847
20833
|
"src/stateWorkspace.ts"() {
|
|
20848
20834
|
"use strict";
|
|
20849
20835
|
init_state_backend();
|
|
20850
|
-
RUNTIME_ROOT =
|
|
20836
|
+
RUNTIME_ROOT = path46.join(".kody-engine", "runtime");
|
|
20851
20837
|
hydratedWorkspaces = /* @__PURE__ */ new Set();
|
|
20852
20838
|
}
|
|
20853
20839
|
});
|
|
@@ -20918,9 +20904,9 @@ var init_tools = __esm({
|
|
|
20918
20904
|
|
|
20919
20905
|
// src/executor.ts
|
|
20920
20906
|
import { spawn as spawn8 } from "child_process";
|
|
20921
|
-
import * as
|
|
20907
|
+
import * as fs49 from "fs";
|
|
20922
20908
|
import * as os7 from "os";
|
|
20923
|
-
import * as
|
|
20909
|
+
import * as path47 from "path";
|
|
20924
20910
|
function isMutatingPostflight(scriptName) {
|
|
20925
20911
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
20926
20912
|
}
|
|
@@ -21161,7 +21147,7 @@ async function runImplementation(profileName, input) {
|
|
|
21161
21147
|
const jobWhyBlock = typeof ctx.data.jobWhy === "string" ? operatorRequestBlock(ctx.data.jobWhy) : null;
|
|
21162
21148
|
const jobRefBlock = jobReferenceBlock(profileName, profile, ctx.data);
|
|
21163
21149
|
const invokeAgent = async (prompt) => {
|
|
21164
|
-
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) =>
|
|
21150
|
+
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path47.isAbsolute(p) ? p : path47.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
21165
21151
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
21166
21152
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
21167
21153
|
const agents = loadSubagents(profile);
|
|
@@ -21623,17 +21609,17 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
21623
21609
|
function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
21624
21610
|
const found = resolveImplementation(profileName, getRuntimeProfileRootsForCwd(cwd));
|
|
21625
21611
|
if (found) return found;
|
|
21626
|
-
const here =
|
|
21612
|
+
const here = path47.dirname(new URL(import.meta.url).pathname);
|
|
21627
21613
|
const candidates = [
|
|
21628
|
-
|
|
21614
|
+
path47.join(here, "implementations", profileName, "profile.json"),
|
|
21629
21615
|
// same-dir sibling (dev)
|
|
21630
|
-
|
|
21616
|
+
path47.join(here, "..", "implementations", profileName, "profile.json"),
|
|
21631
21617
|
// up one (prod: dist/bin → dist/implementations)
|
|
21632
|
-
|
|
21618
|
+
path47.join(here, "..", "src", "implementations", profileName, "profile.json")
|
|
21633
21619
|
// fallback
|
|
21634
21620
|
];
|
|
21635
21621
|
for (const c of candidates) {
|
|
21636
|
-
if (
|
|
21622
|
+
if (fs49.existsSync(c)) return c;
|
|
21637
21623
|
}
|
|
21638
21624
|
return candidates[0];
|
|
21639
21625
|
}
|
|
@@ -21748,15 +21734,15 @@ function resolveShellTimeoutMs(entry) {
|
|
|
21748
21734
|
}
|
|
21749
21735
|
async function runShellEntry(entry, ctx, profile) {
|
|
21750
21736
|
const shellName = entry.shell;
|
|
21751
|
-
const shellPath =
|
|
21752
|
-
if (!
|
|
21737
|
+
const shellPath = path47.join(profile.dir, shellName);
|
|
21738
|
+
if (!fs49.existsSync(shellPath)) {
|
|
21753
21739
|
ctx.skipAgent = true;
|
|
21754
21740
|
ctx.output.exitCode = 99;
|
|
21755
21741
|
ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
|
|
21756
21742
|
return;
|
|
21757
21743
|
}
|
|
21758
21744
|
const positional = entry.with ? Object.values(entry.with).map((v) => String(v)) : [];
|
|
21759
|
-
const outputFile =
|
|
21745
|
+
const outputFile = path47.join(
|
|
21760
21746
|
os7.tmpdir(),
|
|
21761
21747
|
`kody-shell-output-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
21762
21748
|
);
|
|
@@ -21828,9 +21814,9 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
21828
21814
|
}
|
|
21829
21815
|
let sideChannelText = "";
|
|
21830
21816
|
try {
|
|
21831
|
-
if (
|
|
21832
|
-
sideChannelText =
|
|
21833
|
-
|
|
21817
|
+
if (fs49.existsSync(outputFile)) {
|
|
21818
|
+
sideChannelText = fs49.readFileSync(outputFile, "utf-8");
|
|
21819
|
+
fs49.rmSync(outputFile, { force: true });
|
|
21834
21820
|
}
|
|
21835
21821
|
} catch {
|
|
21836
21822
|
}
|
|
@@ -22002,7 +21988,7 @@ __export(job_exports, {
|
|
|
22002
21988
|
stableJobKey: () => stableJobKey,
|
|
22003
21989
|
validateJob: () => validateJob
|
|
22004
21990
|
});
|
|
22005
|
-
import * as
|
|
21991
|
+
import * as path48 from "path";
|
|
22006
21992
|
function newJobId(flavor) {
|
|
22007
21993
|
localJobSeq += 1;
|
|
22008
21994
|
const runId = process.env.GITHUB_RUN_ID;
|
|
@@ -22091,6 +22077,7 @@ async function runJob(job, base) {
|
|
|
22091
22077
|
const persistedState = valid.workflowRunId && workflowIdentity && base.config ? await readWorkflowRunState(base.config, base.cwd, workflowIdentity, valid.workflowRunId) : null;
|
|
22092
22078
|
const workflowJob = {
|
|
22093
22079
|
...workflowContext && !valid.why ? { ...valid, why: workflowContext.body } : valid,
|
|
22080
|
+
...workflowCapability.config.agent ? { agent: workflowCapability.config.agent } : {},
|
|
22094
22081
|
...valid.workflowState ?? persistedState ? { workflowState: valid.workflowState ?? persistedState ?? void 0 } : {}
|
|
22095
22082
|
};
|
|
22096
22083
|
const checkpoint = valid.workflowRunId && workflowIdentity && base.config ? (state) => writeWorkflowRunState(base.config, base.cwd, workflowIdentity, valid.workflowRunId, state) : void 0;
|
|
@@ -22517,11 +22504,11 @@ function selectWorkflowTransition(step, data, counts) {
|
|
|
22517
22504
|
}
|
|
22518
22505
|
function workflowResultConditionPaths(transitions) {
|
|
22519
22506
|
return transitions.flatMap(
|
|
22520
|
-
(transition) => Object.keys(transition.when ?? {}).filter((
|
|
22507
|
+
(transition) => Object.keys(transition.when ?? {}).filter((path54) => path54.startsWith("result."))
|
|
22521
22508
|
);
|
|
22522
22509
|
}
|
|
22523
22510
|
function conditionMatches(condition, context) {
|
|
22524
|
-
return Object.entries(condition).every(([
|
|
22511
|
+
return Object.entries(condition).every(([path54, expected]) => valueMatches(resolveDottedPath2(context, path54), expected));
|
|
22525
22512
|
}
|
|
22526
22513
|
function withWorkflowBoundaryEval(capability, result) {
|
|
22527
22514
|
const capabilityKind = capability.config.capabilityKind;
|
|
@@ -22573,7 +22560,7 @@ function workflowStepToJob(step, parent, chainData) {
|
|
|
22573
22560
|
capability: step.capability,
|
|
22574
22561
|
...step.implementation ? { implementation: step.implementation } : {},
|
|
22575
22562
|
...composeStepWhy(parent.why, step) ? { why: composeStepWhy(parent.why, step) } : {},
|
|
22576
|
-
...
|
|
22563
|
+
...parent.agent ? { agent: parent.agent } : {},
|
|
22577
22564
|
...parent.schedule ? { schedule: parent.schedule } : {},
|
|
22578
22565
|
...typeof target === "number" ? { target } : {},
|
|
22579
22566
|
cliArgs,
|
|
@@ -22679,7 +22666,7 @@ function loadCapabilityContext(slug, cwd) {
|
|
|
22679
22666
|
return resolveCapabilityFolder(slug, hydratedCapabilitiesRoot(cwd));
|
|
22680
22667
|
}
|
|
22681
22668
|
function hydratedCapabilitiesRoot(cwd) {
|
|
22682
|
-
return
|
|
22669
|
+
return path48.join(cwd, ".kody-engine", "definitions", "capabilities");
|
|
22683
22670
|
}
|
|
22684
22671
|
function loadWorkflowContext(slug, base) {
|
|
22685
22672
|
if (!slug || !isWorkflowDefinitionId(slug)) return null;
|
|
@@ -22844,7 +22831,7 @@ function translateOpenAISseToBrain(opts) {
|
|
|
22844
22831
|
|
|
22845
22832
|
// src/servers/brain-serve.ts
|
|
22846
22833
|
import { createServer as createServer2 } from "http";
|
|
22847
|
-
import * as
|
|
22834
|
+
import * as path52 from "path";
|
|
22848
22835
|
|
|
22849
22836
|
// src/chat/loop.ts
|
|
22850
22837
|
init_agent();
|
|
@@ -23886,7 +23873,7 @@ init_config();
|
|
|
23886
23873
|
|
|
23887
23874
|
// src/definition-hydration.ts
|
|
23888
23875
|
init_state_backend();
|
|
23889
|
-
import { createHash as
|
|
23876
|
+
import { createHash as createHash2 } from "crypto";
|
|
23890
23877
|
import * as fs16 from "fs";
|
|
23891
23878
|
import * as path17 from "path";
|
|
23892
23879
|
var SLUG_RE = /^[a-z0-9][a-z0-9_-]{0,127}$/;
|
|
@@ -23907,7 +23894,7 @@ function normalizeDefinitionBundle(bundle) {
|
|
|
23907
23894
|
return { schemaVersion: 1, files };
|
|
23908
23895
|
}
|
|
23909
23896
|
function definitionVersion(bundle) {
|
|
23910
|
-
return `sha256:${
|
|
23897
|
+
return `sha256:${createHash2("sha256").update(JSON.stringify(normalizeDefinitionBundle(bundle))).digest("hex")}`;
|
|
23911
23898
|
}
|
|
23912
23899
|
function verifyDefinition(definition) {
|
|
23913
23900
|
if (!SLUG_RE.test(definition.slug)) throw new Error(`invalid definition slug: ${definition.slug}`);
|
|
@@ -24018,8 +24005,8 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
|
|
|
24018
24005
|
|
|
24019
24006
|
// src/kody-cli.ts
|
|
24020
24007
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
24021
|
-
import * as
|
|
24022
|
-
import * as
|
|
24008
|
+
import * as fs51 from "fs";
|
|
24009
|
+
import * as path50 from "path";
|
|
24023
24010
|
|
|
24024
24011
|
// src/app-auth.ts
|
|
24025
24012
|
import { createSign } from "crypto";
|
|
@@ -24655,6 +24642,74 @@ function readRunRequestFromEnv(env = process.env) {
|
|
|
24655
24642
|
|
|
24656
24643
|
// src/kody-cli.ts
|
|
24657
24644
|
init_runtimePaths();
|
|
24645
|
+
|
|
24646
|
+
// src/loopDefinitions.ts
|
|
24647
|
+
init_definition_paths();
|
|
24648
|
+
import * as fs50 from "fs";
|
|
24649
|
+
import * as path49 from "path";
|
|
24650
|
+
var ID = /^[a-z0-9][a-z0-9_-]{0,79}$/;
|
|
24651
|
+
function normalizeLoopDefinition(value) {
|
|
24652
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
24653
|
+
const raw = value;
|
|
24654
|
+
if (Object.keys(raw).some((key) => !["id", "trigger", "target", "input", "enabled"].includes(key))) return null;
|
|
24655
|
+
if (typeof raw.id !== "string" || !ID.test(raw.id)) return null;
|
|
24656
|
+
if (typeof raw.enabled !== "boolean") return null;
|
|
24657
|
+
if (!isObject(raw.input) || !isObject(raw.trigger) || !isObject(raw.target)) return null;
|
|
24658
|
+
const targetKind = raw.target.kind;
|
|
24659
|
+
const targetId = raw.target.id;
|
|
24660
|
+
if (targetKind !== "workflow" && targetKind !== "capability" || typeof targetId !== "string" || !ID.test(targetId)) {
|
|
24661
|
+
return null;
|
|
24662
|
+
}
|
|
24663
|
+
const trigger = normalizeTrigger(raw.trigger);
|
|
24664
|
+
if (!trigger) return null;
|
|
24665
|
+
return {
|
|
24666
|
+
id: raw.id,
|
|
24667
|
+
trigger,
|
|
24668
|
+
target: { kind: targetKind, id: targetId },
|
|
24669
|
+
input: raw.input,
|
|
24670
|
+
enabled: raw.enabled
|
|
24671
|
+
};
|
|
24672
|
+
}
|
|
24673
|
+
function readLoopDefinition(cwd, id) {
|
|
24674
|
+
if (!ID.test(id)) return null;
|
|
24675
|
+
const roots = [
|
|
24676
|
+
path49.join(cwd, ".kody-engine", "runtime"),
|
|
24677
|
+
definitionsRoot(cwd)
|
|
24678
|
+
];
|
|
24679
|
+
for (const root of roots) {
|
|
24680
|
+
const filePath = path49.join(root, "loops", id, "loop.json");
|
|
24681
|
+
if (!fs50.existsSync(filePath)) continue;
|
|
24682
|
+
try {
|
|
24683
|
+
const loop = normalizeLoopDefinition(JSON.parse(fs50.readFileSync(filePath, "utf8")));
|
|
24684
|
+
if (loop?.id === id) return loop;
|
|
24685
|
+
} catch {
|
|
24686
|
+
}
|
|
24687
|
+
}
|
|
24688
|
+
return null;
|
|
24689
|
+
}
|
|
24690
|
+
function normalizeTrigger(raw) {
|
|
24691
|
+
if (raw.type === "manual" && Object.keys(raw).length === 1) return { type: "manual" };
|
|
24692
|
+
if (raw.type === "schedule" && typeof raw.every === "string" && /^\d+[mhd]$/.test(raw.every)) {
|
|
24693
|
+
if (raw.at === void 0 && Object.keys(raw).every((key) => key === "type" || key === "every")) {
|
|
24694
|
+
return { type: "schedule", every: raw.every };
|
|
24695
|
+
}
|
|
24696
|
+
if (isObject(raw.at) && typeof raw.at.time === "string" && typeof raw.at.timezone === "string" && Object.keys(raw.at).every((key) => key === "time" || key === "timezone") && Object.keys(raw).every((key) => key === "type" || key === "every" || key === "at")) {
|
|
24697
|
+
return { type: "schedule", every: raw.every, at: { time: raw.at.time, timezone: raw.at.timezone } };
|
|
24698
|
+
}
|
|
24699
|
+
}
|
|
24700
|
+
if ((raw.type === "event" || raw.type === "webhook") && typeof raw.event === "string" && raw.event.trim() && Object.keys(raw).every((key) => key === "type" || key === "event")) {
|
|
24701
|
+
return { type: raw.type, event: raw.event.trim() };
|
|
24702
|
+
}
|
|
24703
|
+
if (raw.type === "condition" && typeof raw.expression === "string" && raw.expression.trim() && Object.keys(raw).every((key) => key === "type" || key === "expression")) {
|
|
24704
|
+
return { type: "condition", expression: raw.expression.trim() };
|
|
24705
|
+
}
|
|
24706
|
+
return null;
|
|
24707
|
+
}
|
|
24708
|
+
function isObject(value) {
|
|
24709
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
24710
|
+
}
|
|
24711
|
+
|
|
24712
|
+
// src/kody-cli.ts
|
|
24658
24713
|
init_stateWorkspace();
|
|
24659
24714
|
init_workflowDefinitions();
|
|
24660
24715
|
var FAILED_DISPATCH_LABEL = {
|
|
@@ -24832,9 +24887,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
24832
24887
|
return void 0;
|
|
24833
24888
|
}
|
|
24834
24889
|
function detectPackageManager2(cwd) {
|
|
24835
|
-
if (
|
|
24836
|
-
if (
|
|
24837
|
-
if (
|
|
24890
|
+
if (fs51.existsSync(path50.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
24891
|
+
if (fs51.existsSync(path50.join(cwd, "yarn.lock"))) return "yarn";
|
|
24892
|
+
if (fs51.existsSync(path50.join(cwd, "bun.lockb"))) return "bun";
|
|
24838
24893
|
return "npm";
|
|
24839
24894
|
}
|
|
24840
24895
|
function shouldChainScheduledWatch(match) {
|
|
@@ -24927,8 +24982,8 @@ function postFailureTail(issueNumber, cwd, reason) {
|
|
|
24927
24982
|
const logPath = lastRunLogPath(cwd);
|
|
24928
24983
|
let tail = "";
|
|
24929
24984
|
try {
|
|
24930
|
-
if (
|
|
24931
|
-
const content =
|
|
24985
|
+
if (fs51.existsSync(logPath)) {
|
|
24986
|
+
const content = fs51.readFileSync(logPath, "utf-8");
|
|
24932
24987
|
tail = content.slice(-3e3);
|
|
24933
24988
|
}
|
|
24934
24989
|
} catch {
|
|
@@ -24957,7 +25012,7 @@ async function runCi(argv) {
|
|
|
24957
25012
|
return 0;
|
|
24958
25013
|
}
|
|
24959
25014
|
const args = parseCiArgs(argv);
|
|
24960
|
-
const cwd = args.cwd ?
|
|
25015
|
+
const cwd = args.cwd ? path50.resolve(args.cwd) : process.cwd();
|
|
24961
25016
|
try {
|
|
24962
25017
|
const n = unpackAllSecrets();
|
|
24963
25018
|
if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
|
|
@@ -25016,9 +25071,9 @@ async function runCi(argv) {
|
|
|
25016
25071
|
forceRunCliArgs = { goal: envForceMessage };
|
|
25017
25072
|
}
|
|
25018
25073
|
}
|
|
25019
|
-
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath &&
|
|
25074
|
+
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath && fs51.existsSync(dispatchEventPath)) {
|
|
25020
25075
|
try {
|
|
25021
|
-
const evt = JSON.parse(
|
|
25076
|
+
const evt = JSON.parse(fs51.readFileSync(dispatchEventPath, "utf-8"));
|
|
25022
25077
|
const inputs = objectValue2(evt.inputs);
|
|
25023
25078
|
const issueInput = parseInt(String(inputs?.issue_number ?? ""), 10);
|
|
25024
25079
|
const sessionInput = String(inputs?.sessionId ?? "");
|
|
@@ -25068,7 +25123,9 @@ async function runCi(argv) {
|
|
|
25068
25123
|
workflow: forceRunAction,
|
|
25069
25124
|
cliArgs: {}
|
|
25070
25125
|
};
|
|
25071
|
-
const
|
|
25126
|
+
const loop = manualGoalManager || capabilityRoute || workflowRoute ? null : readLoopDefinition(cwd, forceRunAction);
|
|
25127
|
+
const loopRoute = loop ? loop.target.kind === "workflow" ? { workflow: loop.target.id, cliArgs: loop.input } : { capability: loop.target.id, action: loop.target.id, cliArgs: loop.input } : void 0;
|
|
25128
|
+
const scheduledWatchRoute = manualGoalManager || capabilityRoute || workflowRoute || loopRoute ? void 0 : dispatchScheduledWatches({ force: true, cwd }).find(
|
|
25072
25129
|
(match) => match.action === forceRunAction || match.capability === forceRunAction || match.implementation === forceRunAction
|
|
25073
25130
|
);
|
|
25074
25131
|
const route = manualGoalManager ? {
|
|
@@ -25076,7 +25133,7 @@ async function runCi(argv) {
|
|
|
25076
25133
|
capability: "goal-manager",
|
|
25077
25134
|
implementation: "goal-manager",
|
|
25078
25135
|
cliArgs: forceRunCliArgs
|
|
25079
|
-
} : capabilityRoute ?? workflowRoute ?? scheduledWatchRoute;
|
|
25136
|
+
} : capabilityRoute ?? workflowRoute ?? loopRoute ?? scheduledWatchRoute;
|
|
25080
25137
|
if (!route) {
|
|
25081
25138
|
const root = capabilitiesRoot(cwd);
|
|
25082
25139
|
const available = listCapabilityActions(root).map((item) => item.action);
|
|
@@ -25425,8 +25482,8 @@ init_repoWorkspace();
|
|
|
25425
25482
|
|
|
25426
25483
|
// src/scripts/brainTurnLog.ts
|
|
25427
25484
|
init_runtimePaths();
|
|
25428
|
-
import * as
|
|
25429
|
-
import * as
|
|
25485
|
+
import * as fs52 from "fs";
|
|
25486
|
+
import * as path51 from "path";
|
|
25430
25487
|
import posixPath4 from "path/posix";
|
|
25431
25488
|
var live = /* @__PURE__ */ new Map();
|
|
25432
25489
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -25434,8 +25491,8 @@ function brainEventsFilePath(dir, chatId) {
|
|
|
25434
25491
|
}
|
|
25435
25492
|
function lastPersistedSeq(dir, chatId) {
|
|
25436
25493
|
const p = brainEventsFilePath(dir, chatId);
|
|
25437
|
-
if (!
|
|
25438
|
-
const lines =
|
|
25494
|
+
if (!fs52.existsSync(p)) return 0;
|
|
25495
|
+
const lines = fs52.readFileSync(p, "utf-8").split("\n").filter(Boolean);
|
|
25439
25496
|
if (lines.length === 0) return 0;
|
|
25440
25497
|
try {
|
|
25441
25498
|
return JSON.parse(lines[lines.length - 1]).seq || 0;
|
|
@@ -25445,9 +25502,9 @@ function lastPersistedSeq(dir, chatId) {
|
|
|
25445
25502
|
}
|
|
25446
25503
|
function readSince(dir, chatId, since) {
|
|
25447
25504
|
const p = brainEventsFilePath(dir, chatId);
|
|
25448
|
-
if (!
|
|
25505
|
+
if (!fs52.existsSync(p)) return [];
|
|
25449
25506
|
const out = [];
|
|
25450
|
-
for (const line of
|
|
25507
|
+
for (const line of fs52.readFileSync(p, "utf-8").split("\n")) {
|
|
25451
25508
|
if (!line) continue;
|
|
25452
25509
|
try {
|
|
25453
25510
|
const rec = JSON.parse(line);
|
|
@@ -25473,12 +25530,12 @@ function beginTurn(dir, chatId) {
|
|
|
25473
25530
|
};
|
|
25474
25531
|
live.set(chatId, state);
|
|
25475
25532
|
const p = brainEventsFilePath(dir, chatId);
|
|
25476
|
-
|
|
25533
|
+
fs52.mkdirSync(path51.dirname(p), { recursive: true });
|
|
25477
25534
|
return (event) => {
|
|
25478
25535
|
state.seq += 1;
|
|
25479
25536
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
25480
25537
|
try {
|
|
25481
|
-
|
|
25538
|
+
fs52.appendFileSync(p, `${JSON.stringify(rec)}
|
|
25482
25539
|
`);
|
|
25483
25540
|
} catch (err) {
|
|
25484
25541
|
process.stderr.write(
|
|
@@ -25517,7 +25574,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
|
|
|
25517
25574
|
event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
|
|
25518
25575
|
};
|
|
25519
25576
|
try {
|
|
25520
|
-
|
|
25577
|
+
fs52.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
|
|
25521
25578
|
`);
|
|
25522
25579
|
} catch {
|
|
25523
25580
|
}
|
|
@@ -25910,7 +25967,7 @@ function buildServer(opts) {
|
|
|
25910
25967
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
25911
25968
|
const createStore = opts.createStore ?? createSessionStore;
|
|
25912
25969
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
25913
|
-
const reposRoot = opts.reposRoot ??
|
|
25970
|
+
const reposRoot = opts.reposRoot ?? path52.join(path52.dirname(path52.resolve(opts.cwd)), "repos");
|
|
25914
25971
|
return createServer2(async (req, res) => {
|
|
25915
25972
|
if (!req.method || !req.url) {
|
|
25916
25973
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -26514,7 +26571,7 @@ async function loadConfigSafe() {
|
|
|
26514
26571
|
}
|
|
26515
26572
|
|
|
26516
26573
|
// src/chat-cli.ts
|
|
26517
|
-
import * as
|
|
26574
|
+
import * as path53 from "path";
|
|
26518
26575
|
|
|
26519
26576
|
// src/chat/inbox.ts
|
|
26520
26577
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
@@ -26795,7 +26852,7 @@ async function runChat(argv) {
|
|
|
26795
26852
|
${CHAT_HELP}`);
|
|
26796
26853
|
return 64;
|
|
26797
26854
|
}
|
|
26798
|
-
const cwd = args.cwd ?
|
|
26855
|
+
const cwd = args.cwd ? path53.resolve(args.cwd) : process.cwd();
|
|
26799
26856
|
const sessionId = args.sessionId;
|
|
26800
26857
|
const runRequest = readRunRequestFromEnv();
|
|
26801
26858
|
if (runRequest && "request" in runRequest) {
|
|
@@ -26985,8 +27042,8 @@ var FlyClient = class {
|
|
|
26985
27042
|
get fetch() {
|
|
26986
27043
|
return this.opts.fetchImpl ?? fetch;
|
|
26987
27044
|
}
|
|
26988
|
-
async call(
|
|
26989
|
-
const res = await this.fetch(`${FLY_API_BASE}${
|
|
27045
|
+
async call(path54, init = {}) {
|
|
27046
|
+
const res = await this.fetch(`${FLY_API_BASE}${path54}`, {
|
|
26990
27047
|
method: init.method ?? "GET",
|
|
26991
27048
|
headers: {
|
|
26992
27049
|
Authorization: `Bearer ${this.opts.token}`,
|
|
@@ -26997,7 +27054,7 @@ var FlyClient = class {
|
|
|
26997
27054
|
if (res.status === 404 && init.allow404) return null;
|
|
26998
27055
|
if (!res.ok) {
|
|
26999
27056
|
const text2 = await res.text().catch(() => "");
|
|
27000
|
-
throw new Error(`Fly API ${res.status} on ${
|
|
27057
|
+
throw new Error(`Fly API ${res.status} on ${path54}: ${text2.slice(0, 200) || res.statusText}`);
|
|
27001
27058
|
}
|
|
27002
27059
|
if (res.status === 204) return null;
|
|
27003
27060
|
const raw = await res.text();
|
|
@@ -27750,7 +27807,7 @@ async function poolServe() {
|
|
|
27750
27807
|
|
|
27751
27808
|
// src/servers/runner-serve.ts
|
|
27752
27809
|
import { spawn as spawn9 } from "child_process";
|
|
27753
|
-
import * as
|
|
27810
|
+
import * as fs53 from "fs";
|
|
27754
27811
|
import { createServer as createServer6 } from "http";
|
|
27755
27812
|
var DEFAULT_PORT2 = 8080;
|
|
27756
27813
|
var DEFAULT_WORKDIR = "/workspace/repo";
|
|
@@ -27885,8 +27942,8 @@ async function defaultRunJob(job) {
|
|
|
27885
27942
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
27886
27943
|
const branch = job.ref ?? "main";
|
|
27887
27944
|
const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
|
|
27888
|
-
|
|
27889
|
-
|
|
27945
|
+
fs53.rmSync(workdir, { recursive: true, force: true });
|
|
27946
|
+
fs53.mkdirSync(workdir, { recursive: true });
|
|
27890
27947
|
const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
|
|
27891
27948
|
const target = job.runRequest.target;
|
|
27892
27949
|
const interactive = target.type === "chat";
|