@kody-ade/kody-engine 0.4.303 → 0.4.305
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 +207 -169
- package/package.json +1 -1
package/dist/bin/kody.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "@kody-ade/kody-engine",
|
|
18
|
-
version: "0.4.
|
|
18
|
+
version: "0.4.305",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -10969,7 +10969,7 @@ QA_GOAL_TARGETED=(no manifest issue) (id: ${goalId}, verdict: ${verdict})
|
|
|
10969
10969
|
});
|
|
10970
10970
|
ctx.output.exitCode = verdict === "FAIL" ? 1 : 0;
|
|
10971
10971
|
}
|
|
10972
|
-
var MANIFEST_LABEL, MANIFEST_TITLE, MANIFEST_START, MANIFEST_END, FINDING_LABEL, REPORT_JSON_OPEN, REPORT_JSON_CLOSE, SEVERITY_COLORS, createQaGoal;
|
|
10972
|
+
var MANIFEST_LABEL, MANIFEST_TITLE, MANIFEST_START, MANIFEST_END, FINDING_LABEL, QA_REPORT_LABEL, REPORT_JSON_OPEN, REPORT_JSON_CLOSE, SEVERITY_COLORS, createQaGoal;
|
|
10973
10973
|
var init_createQaGoal = __esm({
|
|
10974
10974
|
"src/scripts/createQaGoal.ts"() {
|
|
10975
10975
|
"use strict";
|
|
@@ -10982,6 +10982,7 @@ var init_createQaGoal = __esm({
|
|
|
10982
10982
|
MANIFEST_START = "<!-- kody-goals-start -->";
|
|
10983
10983
|
MANIFEST_END = "<!-- kody-goals-end -->";
|
|
10984
10984
|
FINDING_LABEL = "kody:qa-finding";
|
|
10985
|
+
QA_REPORT_LABEL = "kody:qa-report";
|
|
10985
10986
|
REPORT_JSON_OPEN = "<!-- KODY_QA_REPORT_JSON";
|
|
10986
10987
|
REPORT_JSON_CLOSE = "-->";
|
|
10987
10988
|
SEVERITY_COLORS = {
|
|
@@ -11021,6 +11022,11 @@ var init_createQaGoal = __esm({
|
|
|
11021
11022
|
ctx.data.action = failedAction2(ctx.output.reason);
|
|
11022
11023
|
return;
|
|
11023
11024
|
}
|
|
11025
|
+
try {
|
|
11026
|
+
ensureLabel(QA_REPORT_LABEL, "8b5cf6", "kody: QA report", ctx.cwd);
|
|
11027
|
+
gh(["issue", "edit", String(existingIssue), "--add-label", QA_REPORT_LABEL], { cwd: ctx.cwd });
|
|
11028
|
+
} catch {
|
|
11029
|
+
}
|
|
11024
11030
|
process.stdout.write(
|
|
11025
11031
|
`
|
|
11026
11032
|
QA_REPORT_POSTED=https://github.com/${ctx.config.github.owner}/${ctx.config.github.repo}/issues/${existingIssue} (verdict: ${verdict})
|
|
@@ -14163,6 +14169,13 @@ function ensureLabel2(cwd) {
|
|
|
14163
14169
|
return false;
|
|
14164
14170
|
}
|
|
14165
14171
|
}
|
|
14172
|
+
function markIssueWithReportLabel(issue, cwd) {
|
|
14173
|
+
if (!ensureLabel2(cwd)) return;
|
|
14174
|
+
try {
|
|
14175
|
+
gh(["issue", "edit", String(issue), "--add-label", QA_LABEL], { cwd });
|
|
14176
|
+
} catch {
|
|
14177
|
+
}
|
|
14178
|
+
}
|
|
14166
14179
|
function createQaIssue(title, body, hasLabel, cwd) {
|
|
14167
14180
|
const args = ["issue", "create", "--title", title, "--body-file", "-"];
|
|
14168
14181
|
if (hasLabel) args.push("--label", QA_LABEL);
|
|
@@ -14204,6 +14217,7 @@ var init_openQaIssue = __esm({
|
|
|
14204
14217
|
if (typeof existingIssue === "number" && Number.isFinite(existingIssue) && existingIssue > 0) {
|
|
14205
14218
|
try {
|
|
14206
14219
|
postIssueComment(existingIssue, reportBody, ctx.cwd);
|
|
14220
|
+
markIssueWithReportLabel(existingIssue, ctx.cwd);
|
|
14207
14221
|
} catch (err) {
|
|
14208
14222
|
const msg = err instanceof Error ? err.message : String(err);
|
|
14209
14223
|
ctx.output.exitCode = 4;
|
|
@@ -15812,165 +15826,6 @@ var init_runFlow = __esm({
|
|
|
15812
15826
|
}
|
|
15813
15827
|
});
|
|
15814
15828
|
|
|
15815
|
-
// src/scripts/previewBuildHelpers.ts
|
|
15816
|
-
import { createDecipheriv, createHash as createHash3 } from "crypto";
|
|
15817
|
-
function shortHash(s) {
|
|
15818
|
-
return createHash3("sha256").update(s).digest("hex").slice(0, 6);
|
|
15819
|
-
}
|
|
15820
|
-
function previewAppName(repo, pr) {
|
|
15821
|
-
const [owner, name] = repo.split("/");
|
|
15822
|
-
if (!owner || !name) {
|
|
15823
|
-
throw new Error(`invalid repo "${repo}", expected "owner/name"`);
|
|
15824
|
-
}
|
|
15825
|
-
return `kp-${shortHash(owner)}-${shortHash(name)}-pr-${pr}`;
|
|
15826
|
-
}
|
|
15827
|
-
function basePreviewAppName(repo) {
|
|
15828
|
-
const [owner, name] = repo.split("/");
|
|
15829
|
-
if (!owner || !name) {
|
|
15830
|
-
throw new Error(`invalid repo "${repo}", expected "owner/name"`);
|
|
15831
|
-
}
|
|
15832
|
-
return `kp-${shortHash(owner)}-${shortHash(name)}-base`;
|
|
15833
|
-
}
|
|
15834
|
-
function decryptVaultPayload(payload, keyRaw) {
|
|
15835
|
-
const parts = payload.split(":");
|
|
15836
|
-
if (parts.length !== 4 || parts[0] !== "v1") {
|
|
15837
|
-
throw new Error("invalid vault payload format");
|
|
15838
|
-
}
|
|
15839
|
-
const [, ivB64, ctB64, tagB64] = parts;
|
|
15840
|
-
const key = /^[0-9a-fA-F]{64}$/.test(keyRaw) ? Buffer.from(keyRaw, "hex") : Buffer.from(keyRaw, "base64");
|
|
15841
|
-
if (key.length !== 32) {
|
|
15842
|
-
throw new Error("KODY_MASTER_KEY must decode to 32 bytes");
|
|
15843
|
-
}
|
|
15844
|
-
const iv = Buffer.from(ivB64, "base64");
|
|
15845
|
-
const ct = Buffer.from(ctB64, "base64");
|
|
15846
|
-
const tag = Buffer.from(tagB64, "base64");
|
|
15847
|
-
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
15848
|
-
decipher.setAuthTag(tag);
|
|
15849
|
-
return Buffer.concat([decipher.update(ct), decipher.final()]).toString("utf8");
|
|
15850
|
-
}
|
|
15851
|
-
function buildEnvFromVault(doc) {
|
|
15852
|
-
const buildEnv = {};
|
|
15853
|
-
for (const [name, entry] of Object.entries(doc.secrets ?? {})) {
|
|
15854
|
-
if (!entry?.value) continue;
|
|
15855
|
-
if (NEVER_PASS_TO_BUILD.has(name)) continue;
|
|
15856
|
-
buildEnv[name] = entry.value;
|
|
15857
|
-
}
|
|
15858
|
-
const raw = doc.secrets?.KODY_PREVIEW_BUILD_MODE?.value;
|
|
15859
|
-
const buildMode = raw?.toLowerCase().trim() === "dev" ? "dev" : "prod";
|
|
15860
|
-
return { buildEnv, buildMode };
|
|
15861
|
-
}
|
|
15862
|
-
function formatPreviewComment(args) {
|
|
15863
|
-
const url = `https://${args.appName}.fly.dev`;
|
|
15864
|
-
return [
|
|
15865
|
-
"<!-- kody-fly-preview -->",
|
|
15866
|
-
`\u2705 **Preview ready:** ${url}`,
|
|
15867
|
-
"",
|
|
15868
|
-
`<sub>App: \`${args.appName}\` \xB7 Commit: \`${args.ref.slice(0, 7)}\` \xB7 Updated: ${args.nowIso}</sub>`
|
|
15869
|
-
].join("\n");
|
|
15870
|
-
}
|
|
15871
|
-
function defaultImageTag(repo, ref) {
|
|
15872
|
-
return createHash3("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
|
|
15873
|
-
}
|
|
15874
|
-
var NEVER_PASS_TO_BUILD;
|
|
15875
|
-
var init_previewBuildHelpers = __esm({
|
|
15876
|
-
"src/scripts/previewBuildHelpers.ts"() {
|
|
15877
|
-
"use strict";
|
|
15878
|
-
NEVER_PASS_TO_BUILD = /* @__PURE__ */ new Set([
|
|
15879
|
-
"FLY_API_TOKEN",
|
|
15880
|
-
"FLY_ORG_SLUG",
|
|
15881
|
-
"FLY_DEFAULT_REGION",
|
|
15882
|
-
"KODY_MASTER_KEY",
|
|
15883
|
-
// Preview-config knob; consumed by the dispatcher before spawn.
|
|
15884
|
-
"KODY_PREVIEW_BUILD_MODE"
|
|
15885
|
-
]);
|
|
15886
|
-
}
|
|
15887
|
-
});
|
|
15888
|
-
|
|
15889
|
-
// src/scripts/previewBuildRun.ts
|
|
15890
|
-
import { spawn as spawn4 } from "child_process";
|
|
15891
|
-
async function runCmd(cmd, args, opts = {}) {
|
|
15892
|
-
await new Promise((resolve10, reject) => {
|
|
15893
|
-
const child = spawn4(cmd, args, {
|
|
15894
|
-
cwd: opts.cwd,
|
|
15895
|
-
env: { ...process.env, ...opts.env ?? {} },
|
|
15896
|
-
stdio: opts.input ? ["pipe", "inherit", "inherit"] : "inherit"
|
|
15897
|
-
});
|
|
15898
|
-
if (opts.input && child.stdin) {
|
|
15899
|
-
child.stdin.write(opts.input);
|
|
15900
|
-
child.stdin.end();
|
|
15901
|
-
}
|
|
15902
|
-
child.on("error", reject);
|
|
15903
|
-
child.on("close", (code) => {
|
|
15904
|
-
if (code === 0) resolve10();
|
|
15905
|
-
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
15906
|
-
});
|
|
15907
|
-
});
|
|
15908
|
-
}
|
|
15909
|
-
var init_previewBuildRun = __esm({
|
|
15910
|
-
"src/scripts/previewBuildRun.ts"() {
|
|
15911
|
-
"use strict";
|
|
15912
|
-
}
|
|
15913
|
-
});
|
|
15914
|
-
|
|
15915
|
-
// src/scripts/previewBuildNamespace.ts
|
|
15916
|
-
async function fetchGithubOidcToken(audience) {
|
|
15917
|
-
const url = process.env.ACTIONS_ID_TOKEN_REQUEST_URL?.trim();
|
|
15918
|
-
const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN?.trim();
|
|
15919
|
-
if (!url || !requestToken) return null;
|
|
15920
|
-
const res = await fetch(`${url}&audience=${encodeURIComponent(audience)}`, {
|
|
15921
|
-
headers: { Authorization: `Bearer ${requestToken}` },
|
|
15922
|
-
signal: AbortSignal.timeout(REQ_TIMEOUT_MS)
|
|
15923
|
-
});
|
|
15924
|
-
if (!res.ok) {
|
|
15925
|
-
throw new Error(`OIDC token request failed: ${res.status} ${res.statusText}`);
|
|
15926
|
-
}
|
|
15927
|
-
const data = await res.json();
|
|
15928
|
-
if (!data.value) throw new Error("OIDC token response missing `value`");
|
|
15929
|
-
return data.value;
|
|
15930
|
-
}
|
|
15931
|
-
async function setupNamespaceBuilder(opts) {
|
|
15932
|
-
try {
|
|
15933
|
-
await runCmd("bash", ["-c", NSC_INSTALL]);
|
|
15934
|
-
const jwt = await fetchGithubOidcToken(NSC_OIDC_AUDIENCE);
|
|
15935
|
-
if (!jwt) {
|
|
15936
|
-
console.warn("[preview-build] no GitHub OIDC token (id-token: write missing?) \u2014 local docker build");
|
|
15937
|
-
return null;
|
|
15938
|
-
}
|
|
15939
|
-
await runCmd("nsc", ["auth", "exchange-oidc-token", "--tenant_id", opts.tenantId, "--token", jwt]);
|
|
15940
|
-
await runCmd("nsc", ["docker", "buildx", "setup", "--name", opts.builderName]);
|
|
15941
|
-
console.log(`[preview-build] Namespace remote builder ready (${opts.builderName})`);
|
|
15942
|
-
return opts.builderName;
|
|
15943
|
-
} catch (err) {
|
|
15944
|
-
console.warn(
|
|
15945
|
-
"[preview-build] Namespace setup failed \u2014 falling back to local docker:",
|
|
15946
|
-
err instanceof Error ? err.message : String(err)
|
|
15947
|
-
);
|
|
15948
|
-
return null;
|
|
15949
|
-
}
|
|
15950
|
-
}
|
|
15951
|
-
var NSC_OIDC_AUDIENCE, REQ_TIMEOUT_MS, NSC_INSTALL;
|
|
15952
|
-
var init_previewBuildNamespace = __esm({
|
|
15953
|
-
"src/scripts/previewBuildNamespace.ts"() {
|
|
15954
|
-
"use strict";
|
|
15955
|
-
init_previewBuildRun();
|
|
15956
|
-
NSC_OIDC_AUDIENCE = "https://namespace.so";
|
|
15957
|
-
REQ_TIMEOUT_MS = 15e3;
|
|
15958
|
-
NSC_INSTALL = `
|
|
15959
|
-
set -euo pipefail
|
|
15960
|
-
if [ ! -x /usr/local/bin/nsc ]; then
|
|
15961
|
-
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
|
|
15962
|
-
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
|
15963
|
-
curl -fsSL "https://get.namespace.so/packages/nsc/latest?arch=\${ARCH}&os=\${OS}" -o /tmp/nsc.tar.gz
|
|
15964
|
-
mkdir -p /tmp/nsc-extract
|
|
15965
|
-
tar -xzf /tmp/nsc.tar.gz -C /tmp/nsc-extract
|
|
15966
|
-
NSC_BIN=$(find /tmp/nsc-extract -type f -name nsc | head -1)
|
|
15967
|
-
sudo install -m 0755 "$NSC_BIN" /usr/local/bin/nsc
|
|
15968
|
-
fi
|
|
15969
|
-
/usr/local/bin/nsc version
|
|
15970
|
-
`;
|
|
15971
|
-
}
|
|
15972
|
-
});
|
|
15973
|
-
|
|
15974
15829
|
// src/stateRepoGithub.ts
|
|
15975
15830
|
import * as fs39 from "fs";
|
|
15976
15831
|
import * as path37 from "path";
|
|
@@ -15990,7 +15845,7 @@ async function githubContentsFile(opts) {
|
|
|
15990
15845
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
15991
15846
|
"User-Agent": "kody-engine"
|
|
15992
15847
|
},
|
|
15993
|
-
signal: AbortSignal.timeout(
|
|
15848
|
+
signal: AbortSignal.timeout(REQ_TIMEOUT_MS)
|
|
15994
15849
|
});
|
|
15995
15850
|
if (res.status === 404) return null;
|
|
15996
15851
|
if (!res.ok) {
|
|
@@ -16089,7 +15944,7 @@ async function writeGithubStateTextWithConfig(opts) {
|
|
|
16089
15944
|
"User-Agent": "kody-engine"
|
|
16090
15945
|
},
|
|
16091
15946
|
body: JSON.stringify(payload),
|
|
16092
|
-
signal: AbortSignal.timeout(
|
|
15947
|
+
signal: AbortSignal.timeout(REQ_TIMEOUT_MS)
|
|
16093
15948
|
});
|
|
16094
15949
|
if (!res.ok) {
|
|
16095
15950
|
throw new Error(
|
|
@@ -16143,13 +15998,196 @@ async function persistJsonlFileToGithubState(opts) {
|
|
|
16143
15998
|
}
|
|
16144
15999
|
}
|
|
16145
16000
|
}
|
|
16146
|
-
var GITHUB_API,
|
|
16001
|
+
var GITHUB_API, REQ_TIMEOUT_MS;
|
|
16147
16002
|
var init_stateRepoGithub = __esm({
|
|
16148
16003
|
"src/stateRepoGithub.ts"() {
|
|
16149
16004
|
"use strict";
|
|
16150
16005
|
init_stateRepo();
|
|
16151
16006
|
GITHUB_API = "https://api.github.com";
|
|
16152
|
-
|
|
16007
|
+
REQ_TIMEOUT_MS = 3e4;
|
|
16008
|
+
}
|
|
16009
|
+
});
|
|
16010
|
+
|
|
16011
|
+
// src/scripts/previewBuildHelpers.ts
|
|
16012
|
+
import { createDecipheriv, createHash as createHash3, hkdfSync } from "crypto";
|
|
16013
|
+
function shortHash(s) {
|
|
16014
|
+
return createHash3("sha256").update(s).digest("hex").slice(0, 6);
|
|
16015
|
+
}
|
|
16016
|
+
function previewAppName(repo, pr) {
|
|
16017
|
+
const [owner, name] = repo.split("/");
|
|
16018
|
+
if (!owner || !name) {
|
|
16019
|
+
throw new Error(`invalid repo "${repo}", expected "owner/name"`);
|
|
16020
|
+
}
|
|
16021
|
+
return `kp-${shortHash(owner)}-${shortHash(name)}-pr-${pr}`;
|
|
16022
|
+
}
|
|
16023
|
+
function basePreviewAppName(repo) {
|
|
16024
|
+
const [owner, name] = repo.split("/");
|
|
16025
|
+
if (!owner || !name) {
|
|
16026
|
+
throw new Error(`invalid repo "${repo}", expected "owner/name"`);
|
|
16027
|
+
}
|
|
16028
|
+
return `kp-${shortHash(owner)}-${shortHash(name)}-base`;
|
|
16029
|
+
}
|
|
16030
|
+
function decryptVaultPayload(payload, keyRaw) {
|
|
16031
|
+
const parts = payload.split(":");
|
|
16032
|
+
if (parts.length !== 4 || parts[0] !== "v1") {
|
|
16033
|
+
throw new Error("invalid vault payload format");
|
|
16034
|
+
}
|
|
16035
|
+
const [, ivB64, ctB64, tagB64] = parts;
|
|
16036
|
+
const key = decodeMasterKey(keyRaw);
|
|
16037
|
+
if (key.length !== 32) {
|
|
16038
|
+
throw new Error("KODY_MASTER_KEY must decode to 32 bytes");
|
|
16039
|
+
}
|
|
16040
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
16041
|
+
const ct = Buffer.from(ctB64, "base64");
|
|
16042
|
+
const tag = Buffer.from(tagB64, "base64");
|
|
16043
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
16044
|
+
decipher.setAuthTag(tag);
|
|
16045
|
+
return Buffer.concat([decipher.update(ct), decipher.final()]).toString("utf8");
|
|
16046
|
+
}
|
|
16047
|
+
function decodeMasterKey(keyRaw) {
|
|
16048
|
+
if (/^[0-9a-fA-F]{64}$/.test(keyRaw)) return Buffer.from(keyRaw, "hex");
|
|
16049
|
+
return Buffer.from(keyRaw.replace(/-/g, "+").replace(/_/g, "/"), "base64");
|
|
16050
|
+
}
|
|
16051
|
+
function derivePreviewVerifyKey(masterKeyRaw) {
|
|
16052
|
+
const masterKey = decodeMasterKey(masterKeyRaw);
|
|
16053
|
+
if (masterKey.length !== 32) {
|
|
16054
|
+
throw new Error("KODY_MASTER_KEY must decode to 32 bytes");
|
|
16055
|
+
}
|
|
16056
|
+
return Buffer.from(hkdfSync("sha256", masterKey, Buffer.alloc(0), PREVIEW_KEY_INFO, 32)).toString("hex");
|
|
16057
|
+
}
|
|
16058
|
+
function previewRuntimeEnv(args) {
|
|
16059
|
+
return {
|
|
16060
|
+
...args.buildEnv,
|
|
16061
|
+
KODY_PREVIEW_VERIFY_KEY: derivePreviewVerifyKey(args.masterKey),
|
|
16062
|
+
KODY_REPO_CONTEXT: args.repo,
|
|
16063
|
+
KODY_PR: String(args.pr)
|
|
16064
|
+
};
|
|
16065
|
+
}
|
|
16066
|
+
function buildEnvFromVault(doc) {
|
|
16067
|
+
const buildEnv = {};
|
|
16068
|
+
for (const [name, entry] of Object.entries(doc.secrets ?? {})) {
|
|
16069
|
+
if (!entry?.value) continue;
|
|
16070
|
+
if (NEVER_PASS_TO_BUILD.has(name)) continue;
|
|
16071
|
+
buildEnv[name] = entry.value;
|
|
16072
|
+
}
|
|
16073
|
+
const raw = doc.secrets?.KODY_PREVIEW_BUILD_MODE?.value;
|
|
16074
|
+
const buildMode = raw?.toLowerCase().trim() === "dev" ? "dev" : "prod";
|
|
16075
|
+
return { buildEnv, buildMode };
|
|
16076
|
+
}
|
|
16077
|
+
function formatPreviewComment(args) {
|
|
16078
|
+
const url = `https://${args.appName}.fly.dev`;
|
|
16079
|
+
return [
|
|
16080
|
+
"<!-- kody-fly-preview -->",
|
|
16081
|
+
`\u2705 **Preview ready:** ${url}`,
|
|
16082
|
+
"",
|
|
16083
|
+
`<sub>App: \`${args.appName}\` \xB7 Commit: \`${args.ref.slice(0, 7)}\` \xB7 Updated: ${args.nowIso}</sub>`
|
|
16084
|
+
].join("\n");
|
|
16085
|
+
}
|
|
16086
|
+
function defaultImageTag(repo, ref) {
|
|
16087
|
+
return createHash3("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
|
|
16088
|
+
}
|
|
16089
|
+
var NEVER_PASS_TO_BUILD, PREVIEW_KEY_INFO;
|
|
16090
|
+
var init_previewBuildHelpers = __esm({
|
|
16091
|
+
"src/scripts/previewBuildHelpers.ts"() {
|
|
16092
|
+
"use strict";
|
|
16093
|
+
NEVER_PASS_TO_BUILD = /* @__PURE__ */ new Set([
|
|
16094
|
+
"FLY_API_TOKEN",
|
|
16095
|
+
"FLY_ORG_SLUG",
|
|
16096
|
+
"FLY_DEFAULT_REGION",
|
|
16097
|
+
"KODY_MASTER_KEY",
|
|
16098
|
+
// Preview-config knob; consumed by the dispatcher before spawn.
|
|
16099
|
+
"KODY_PREVIEW_BUILD_MODE",
|
|
16100
|
+
"KODY_PREVIEW_VERIFY_KEY",
|
|
16101
|
+
"KODY_REPO_CONTEXT",
|
|
16102
|
+
"KODY_PR",
|
|
16103
|
+
"KODY_BRANCH"
|
|
16104
|
+
]);
|
|
16105
|
+
PREVIEW_KEY_INFO = "kody-preview:v1";
|
|
16106
|
+
}
|
|
16107
|
+
});
|
|
16108
|
+
|
|
16109
|
+
// src/scripts/previewBuildRun.ts
|
|
16110
|
+
import { spawn as spawn4 } from "child_process";
|
|
16111
|
+
async function runCmd(cmd, args, opts = {}) {
|
|
16112
|
+
await new Promise((resolve10, reject) => {
|
|
16113
|
+
const child = spawn4(cmd, args, {
|
|
16114
|
+
cwd: opts.cwd,
|
|
16115
|
+
env: { ...process.env, ...opts.env ?? {} },
|
|
16116
|
+
stdio: opts.input ? ["pipe", "inherit", "inherit"] : "inherit"
|
|
16117
|
+
});
|
|
16118
|
+
if (opts.input && child.stdin) {
|
|
16119
|
+
child.stdin.write(opts.input);
|
|
16120
|
+
child.stdin.end();
|
|
16121
|
+
}
|
|
16122
|
+
child.on("error", reject);
|
|
16123
|
+
child.on("close", (code) => {
|
|
16124
|
+
if (code === 0) resolve10();
|
|
16125
|
+
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
16126
|
+
});
|
|
16127
|
+
});
|
|
16128
|
+
}
|
|
16129
|
+
var init_previewBuildRun = __esm({
|
|
16130
|
+
"src/scripts/previewBuildRun.ts"() {
|
|
16131
|
+
"use strict";
|
|
16132
|
+
}
|
|
16133
|
+
});
|
|
16134
|
+
|
|
16135
|
+
// src/scripts/previewBuildNamespace.ts
|
|
16136
|
+
async function fetchGithubOidcToken(audience) {
|
|
16137
|
+
const url = process.env.ACTIONS_ID_TOKEN_REQUEST_URL?.trim();
|
|
16138
|
+
const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN?.trim();
|
|
16139
|
+
if (!url || !requestToken) return null;
|
|
16140
|
+
const res = await fetch(`${url}&audience=${encodeURIComponent(audience)}`, {
|
|
16141
|
+
headers: { Authorization: `Bearer ${requestToken}` },
|
|
16142
|
+
signal: AbortSignal.timeout(REQ_TIMEOUT_MS2)
|
|
16143
|
+
});
|
|
16144
|
+
if (!res.ok) {
|
|
16145
|
+
throw new Error(`OIDC token request failed: ${res.status} ${res.statusText}`);
|
|
16146
|
+
}
|
|
16147
|
+
const data = await res.json();
|
|
16148
|
+
if (!data.value) throw new Error("OIDC token response missing `value`");
|
|
16149
|
+
return data.value;
|
|
16150
|
+
}
|
|
16151
|
+
async function setupNamespaceBuilder(opts) {
|
|
16152
|
+
try {
|
|
16153
|
+
await runCmd("bash", ["-c", NSC_INSTALL]);
|
|
16154
|
+
const jwt = await fetchGithubOidcToken(NSC_OIDC_AUDIENCE);
|
|
16155
|
+
if (!jwt) {
|
|
16156
|
+
console.warn("[preview-build] no GitHub OIDC token (id-token: write missing?) \u2014 local docker build");
|
|
16157
|
+
return null;
|
|
16158
|
+
}
|
|
16159
|
+
await runCmd("nsc", ["auth", "exchange-oidc-token", "--tenant_id", opts.tenantId, "--token", jwt]);
|
|
16160
|
+
await runCmd("nsc", ["docker", "buildx", "setup", "--name", opts.builderName]);
|
|
16161
|
+
console.log(`[preview-build] Namespace remote builder ready (${opts.builderName})`);
|
|
16162
|
+
return opts.builderName;
|
|
16163
|
+
} catch (err) {
|
|
16164
|
+
console.warn(
|
|
16165
|
+
"[preview-build] Namespace setup failed \u2014 falling back to local docker:",
|
|
16166
|
+
err instanceof Error ? err.message : String(err)
|
|
16167
|
+
);
|
|
16168
|
+
return null;
|
|
16169
|
+
}
|
|
16170
|
+
}
|
|
16171
|
+
var NSC_OIDC_AUDIENCE, REQ_TIMEOUT_MS2, NSC_INSTALL;
|
|
16172
|
+
var init_previewBuildNamespace = __esm({
|
|
16173
|
+
"src/scripts/previewBuildNamespace.ts"() {
|
|
16174
|
+
"use strict";
|
|
16175
|
+
init_previewBuildRun();
|
|
16176
|
+
NSC_OIDC_AUDIENCE = "https://namespace.so";
|
|
16177
|
+
REQ_TIMEOUT_MS2 = 15e3;
|
|
16178
|
+
NSC_INSTALL = `
|
|
16179
|
+
set -euo pipefail
|
|
16180
|
+
if [ ! -x /usr/local/bin/nsc ]; then
|
|
16181
|
+
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
|
|
16182
|
+
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
|
16183
|
+
curl -fsSL "https://get.namespace.so/packages/nsc/latest?arch=\${ARCH}&os=\${OS}" -o /tmp/nsc.tar.gz
|
|
16184
|
+
mkdir -p /tmp/nsc-extract
|
|
16185
|
+
tar -xzf /tmp/nsc.tar.gz -C /tmp/nsc-extract
|
|
16186
|
+
NSC_BIN=$(find /tmp/nsc-extract -type f -name nsc | head -1)
|
|
16187
|
+
sudo install -m 0755 "$NSC_BIN" /usr/local/bin/nsc
|
|
16188
|
+
fi
|
|
16189
|
+
/usr/local/bin/nsc version
|
|
16190
|
+
`;
|
|
16153
16191
|
}
|
|
16154
16192
|
});
|
|
16155
16193
|
|
|
@@ -16361,10 +16399,10 @@ var FLY_MACHINES, FLY_GRAPHQL, REQ_TIMEOUT_MS3, runPreviewBuild;
|
|
|
16361
16399
|
var init_runPreviewBuild = __esm({
|
|
16362
16400
|
"src/scripts/runPreviewBuild.ts"() {
|
|
16363
16401
|
"use strict";
|
|
16402
|
+
init_stateRepoGithub();
|
|
16364
16403
|
init_previewBuildHelpers();
|
|
16365
16404
|
init_previewBuildNamespace();
|
|
16366
16405
|
init_previewBuildRun();
|
|
16367
|
-
init_stateRepoGithub();
|
|
16368
16406
|
FLY_MACHINES = "https://api.machines.dev/v1";
|
|
16369
16407
|
FLY_GRAPHQL = "https://api.fly.io/graphql";
|
|
16370
16408
|
REQ_TIMEOUT_MS3 = 3e4;
|
|
@@ -16489,7 +16527,7 @@ var init_runPreviewBuild = __esm({
|
|
|
16489
16527
|
appName,
|
|
16490
16528
|
region,
|
|
16491
16529
|
image: `registry.fly.io/${appName}:${tag}`,
|
|
16492
|
-
env: buildEnv
|
|
16530
|
+
env: previewRuntimeEnv({ buildEnv, masterKey, pr, repo })
|
|
16493
16531
|
},
|
|
16494
16532
|
flyToken
|
|
16495
16533
|
);
|
|
@@ -23046,7 +23084,7 @@ async function runCapabilityFallbackTick(deps) {
|
|
|
23046
23084
|
}
|
|
23047
23085
|
|
|
23048
23086
|
// src/pool/keys.ts
|
|
23049
|
-
import { hkdfSync } from "crypto";
|
|
23087
|
+
import { hkdfSync as hkdfSync2 } from "crypto";
|
|
23050
23088
|
var POOL_API_KEY_INFO = "kody-pool-api:v1";
|
|
23051
23089
|
var RUNNER_API_KEY_INFO = "kody-runner-api:v1";
|
|
23052
23090
|
function masterKeyBytes(raw) {
|
|
@@ -23058,7 +23096,7 @@ function masterKeyBytes(raw) {
|
|
|
23058
23096
|
return Buffer.from(v.replace(/-/g, "+").replace(/_/g, "/"), "base64");
|
|
23059
23097
|
}
|
|
23060
23098
|
function deriveKey(master, info, length = 32) {
|
|
23061
|
-
return Buffer.from(
|
|
23099
|
+
return Buffer.from(hkdfSync2("sha256", master, Buffer.alloc(0), info, length)).toString("hex");
|
|
23062
23100
|
}
|
|
23063
23101
|
function derivePoolApiKey(master) {
|
|
23064
23102
|
return deriveKey(master, POOL_API_KEY_INFO);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.305",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|